Commit 4d26cae0 by Hoang Phuc Do

Create layout for user log in, sign up, edit profile page

parent 7099ab3b
......@@ -40,6 +40,8 @@ gem 'bootstrap-sass', '~> 3.3.6'
gem 'faker', '~> 1.6', '>= 1.6.3'
# Kaminari is a Scope & Engine based, clean, powerful, agnostic, customizable and sophisticated paginator for Rails 4+
gem 'kaminari', '~> 1.0', '>= 1.0.1'
# Flexible authentication solution for Rails with Warden
gem 'devise', '~> 4.3'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
......
......@@ -43,6 +43,7 @@ GEM
arel (8.0.0)
autoprefixer-rails (7.1.1)
execjs
bcrypt (3.1.11)
bindex (0.5.0)
bootstrap-sass (3.3.6)
autoprefixer-rails (>= 5.2.1)
......@@ -70,6 +71,12 @@ GEM
execjs
coffee-script-source (1.12.2)
concurrent-ruby (1.0.5)
devise (4.3.0)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.2)
responders
warden (~> 1.2.3)
erubi (1.6.0)
execjs (2.7.0)
faker (1.6.6)
......@@ -113,6 +120,7 @@ GEM
nio4r (2.1.0)
nokogiri (1.8.0)
mini_portile2 (~> 2.2.0)
orm_adapter (0.5.0)
public_suffix (2.0.5)
puma (3.9.1)
rack (2.0.3)
......@@ -145,6 +153,9 @@ GEM
rb-fsevent (0.9.8)
rb-inotify (0.9.8)
ffi (>= 0.5.0)
responders (2.4.0)
actionpack (>= 4.2.0, < 5.3)
railties (>= 4.2.0, < 5.3)
ruby_dep (1.5.0)
rubyzip (1.2.1)
sass (3.4.24)
......@@ -180,6 +191,8 @@ GEM
thread_safe (~> 0.1)
uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
warden (1.2.7)
rack (>= 1.0)
web-console (3.5.1)
actionview (>= 5.0)
activemodel (>= 5.0)
......@@ -201,6 +214,7 @@ DEPENDENCIES
capybara (~> 2.13)
carrierwave (~> 1.0)
coffee-rails (~> 4.2)
devise (~> 4.3)
faker (~> 1.6, >= 1.6.3)
jbuilder (~> 2.5)
kaminari (~> 1.0, >= 1.0.1)
......
a {
color: #000000;
}
a:hover {
color: #0d0d0d;
}
a:focus {
color: #0d0d0d;
}
a:active {
color: #000000;
}
.pagination > li > a,
.pagination > li > span,
.pagination > li > a:hover,
.pagination > li > span:hover,
.pagination > li > a:focus,
.pagination > li > span:focus {
color: #000000;
}
.pagination > .active > a,
.pagination > .active > span,
.pagination > .active > a:hover,
.pagination > .active > span:hover,
.pagination > .active > a:focus,
.pagination > .active > span:focus {
background-color: #000000 !important;
border-color: #000000;
}
html .btn-primary {
color: #ffffff;
background-color: #000000;
border-color: #000000 #000000 #000000;
}
html .btn-primary:hover {
border-color: #0d0d0d #0d0d0d #000000;
background-color: #0d0d0d;
}
html .btn-primary:active,
html .btn-primary:focus,
html .btn-primary:active:hover,
html .btn-primary:active:focus {
border-color: #000000 #000000 #000000;
background-color: #000000;
}
html .btn-primary.dropdown-toggle {
border-left-color: #000000;
}
html .btn-primary[disabled],
html .btn-primary[disabled]:hover,
html .btn-primary[disabled]:active,
html .btn-primary[disabled]:focus {
border-color: #333333;
background-color: #333333;
}
html .btn-primary:hover,
html .btn-primary:focus,
html .btn-primary:active:hover,
html .btn-primary:active:focus {
color: #ffffff;
}
.btn {
border-radius: 0;
}
.featured-box .box-content {
border-radius: 0;
}
\ No newline at end of file
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
<h2>Resend confirmation instructions</h2>
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
</div>
<div class="actions">
<%= f.submit "Resend confirmation instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
<p>Welcome <%= @email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
<p>Hello <%= @email %>!</p>
<% if @resource.try(:unconfirmed_email?) %>
<p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
<% else %>
<p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
<% end %>
<p>Hello <%= @resource.email %>!</p>
<p>We're contacting you to notify you that your password has been changed.</p>
<p>Hello <%= @resource.email %>!</p>
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>
<p>Hello <%= @resource.email %>!</p>
<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
<p>Click the link below to unlock your account:</p>
<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
<h2>Change your password</h2>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
<%= devise_error_messages! %>
<%= f.hidden_field :reset_password_token %>
<div class="field">
<%= f.label :password, "New password" %><br />
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em><br />
<% end %>
<%= f.password_field :password, autofocus: true, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Change my password" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
<h2>Forgot your password?</h2>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="actions">
<%= f.submit "Send me reset password instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
<div class="container">
<div class="row">
<div class="col-md-9 col-md-push-3 my-account form-section">
<h1 class="h2 heading-primary font-weight-normal">
Edit <%= resource_name.to_s.humanize %>
</h1>
<div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md">
<div class="box-content">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<h4 class="heading-primary text-uppercase mb-lg">
ACCOUNT INFORMATION
</h4>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %>
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "off", class: "form-control" %>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-action clearfix mt-none">
<%= f.submit "Submit", class: "btn btn-primary" %>
</div>
</div>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
<section class="form-section register-form">
<div class="container">
<h1 class="h2 heading-primary font-weight-normal mb-md mt-xlg">
Create an Account
</h1>
<div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md">
<div class="box-content">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<h4 class="heading-primary text-uppercase mb-lg">PERSONAL INFORMATION</h4>
<%= devise_error_messages! %>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %>
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-action clearfix mt-none">
<%= f.submit "Submit", class: "btn btn-primary" %>
</div>
</div>
</div>
<% end %>
</div>
</div>
</div>
</section>
<section class="form-section">
<div class="container">
<h2 class="h2 heading-primary font-weight-normal mb-md mt-xlg">
Welcome back! Sign in to your account
</h2>
<div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md">
<div class="box-content">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="form-content">
<h3 class="heading-text-color font-weight-normal">
</h3>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>
</div>
<div class="form-action clearfix">
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Lost your password?", new_password_path(resource_name), class: 'pull-left' %>
<% end -%>
<%= f.submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
</section>
\ No newline at end of file
<%- if controller_name != 'sessions' %>
<%= link_to "Log in", new_session_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br />
<% end -%>
<% end -%>
<h2>Resend unlock instructions</h2>
<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="actions">
<%= f.submit "Resend unlock instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
<header>
<div class="header-container">
</div>
</header>
\ No newline at end of file
......@@ -9,12 +9,8 @@
</head>
<body>
<div id="main-container col2-left-layout">
<div class="container">
<%= yield %>
</div>
<!-- End .container -->
<div role="main" class="main">
<%= yield %>
</div>
<!-- End .main-container -->
</body>
</html>
<li class="item">
<div class="product-img">
<a href="#">
<figure>
<%= image_tag(get_product_thumbnail(product, 170, 204), class: "small-image") %>
</figure>
</a>
</div>
<div class="product-shop">
<h2 class="product-name"><%= product.title %></h2>
<div class="price-box">
<div class="special-price">
<span class="price"><%= number_to_currency(product.price) %></span>
<li class="product-<%= product.id %>">
<div class="product product-list">
<figure class="product-image-area">
<a href="#">
<%= image_tag(get_product_thumbnail(product, 170, 204)) %>
</a>
</figure>
<div class="product-details-area">
<h2 class="product-name">
<%= link_to product.title, '#' %>
</h2>
<div class="product-short-desc">
<%= product.description %>
</div>
<div class="product-price-box">
<span class="product-price"><%= number_to_currency(product.price) %></span>
</div>
</div>
<div class="desc std">
<%= simple_format(product.description) %>
</div>
</div>
</li>
\ No newline at end of file
</li>
<ul class="products-grid">
<div class="products-grid columns3">
<% @recommended_products.each do |product| %>
<li class="item col-lg-4 col-md-4 col-sm-6 col-xs-6 ">
<div class="product-item">
<div class="item-inner">
<div class="product-thumb">
<figure>
<li class="product-<%= product.id %>">
<div class="product">
<figure class="product-image-area">
<a href="#">
<%= image_tag(get_product_thumbnail(product, 170, 204)) %>
</a>
</figure>
</div>
<div class="item-info">
<div class="info-inner">
<div class="item-title">
<%= link_to product.title, "#" %>
</div>
<div class="item-content">
<div class="item-price">
<div class="price-box">
<div class="regular-price">
<span class="price"><%= number_to_currency(product.price) %></span>
</div>
</div>
</div>
<div class="product-details-area">
<h2 class="product-name">
<%= link_to product.title, '#' %>
</h2>
<div class="product-price-box">
<span class="product-price"><%= number_to_currency(product.price) %></span>
</div>
</div>
</div>
</div>
</div>
</li>
</li>
<% end %>
</ul>
\ No newline at end of file
</div>
\ No newline at end of file
<div class="row">
<div class="col-main col-sm-9 col-xs-12 col-sm-push-3">
<div class="shop-inner">
<div class="page-title">
<h1>Recommended Items</h1>
</div>
<div class="product-grid-area">
<div class="container">
<div class="row">
<div class="col-md-9 col-md-push-3">
<h2 class="h2 heading-primary mt-lg clearfix">
<span>Recommended Items</span>
<%= link_to 'Log out', destroy_user_session_path, method: :delete %>
</h2>
<div class="products-grid columns3">
<%= render 'products/recommended' %>
</div>
<div class="page-title">
<h1>Newest Items</h1>
</div>
<div class="product-list-area">
<ul id="products-list" class="products-list">
<%= render @latest_products %>
</ul>
</div>
<h2 class="h2 heading-primary mt-lg clearfix">
<span>Newest Items</span>
</h2>
<ul class="products-list">
<%= render @latest_products %>
</ul>
<div class="pagination-area">
<%= paginate @latest_products %>
<div class="toolbar-bottom">
<div class="toolbar">
<div class="sorter">
<%= paginate @latest_products %>
</div>
</div>
</div>
</div>
</div>
<aside class="sidebar col-sm-3 col-xs-12 col-sm-pull-9">
<%= render 'shared/sidebar' %>
</aside>
</div>
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en:
devise:
confirmations:
confirmed: "Your email address has been successfully confirmed."
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
failure:
already_authenticated: "You are already signed in."
inactive: "Your account is not activated yet."
invalid: "Invalid %{authentication_keys} or password."
locked: "Your account is locked."
last_attempt: "You have one more attempt before your account is locked."
not_found_in_database: "Invalid %{authentication_keys} or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
unconfirmed: "You have to confirm your email address before continuing."
mailer:
confirmation_instructions:
subject: "Confirmation instructions"
reset_password_instructions:
subject: "Reset password instructions"
unlock_instructions:
subject: "Unlock instructions"
email_changed:
subject: "Email Changed"
password_change:
subject: "Password Changed"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
passwords:
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
updated: "Your password has been changed successfully. You are now signed in."
updated_not_active: "Your password has been changed successfully."
registrations:
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
signed_up: "Welcome! You have signed up successfully."
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
updated: "Your account has been updated successfully."
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
already_signed_out: "Signed out successfully."
unlocks:
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
errors:
messages:
already_confirmed: "was already confirmed, please try signing in"
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
expired: "has expired, please request a new one"
not_found: "not found"
not_locked: "was not locked"
not_saved:
one: "1 error prohibited this %{resource} from being saved:"
other: "%{count} errors prohibited this %{resource} from being saved:"
......@@ -2,4 +2,5 @@ Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'static_pages#index'
resources :categories
devise_for :users
end
class DeviseCreateUsers < ActiveRecord::Migration[5.1]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170606064132) do
ActiveRecord::Schema.define(version: 20170608032601) do
create_table "categories", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "title"
......@@ -29,5 +29,22 @@ ActiveRecord::Schema.define(version: 20170606064132) do
t.index ["category_id"], name: "index_products_on_category_id"
end
create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "products", "categories"
end
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