diff --git a/.gitignore b/.gitignore index 7fe04b9..a695304 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ yarn-debug.log* config/settings.local.yml config/settings/*.local.yml config/environments/*.local.yml +config/application.yml diff --git a/Gemfile b/Gemfile index 774eee8..6d42c8a 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ gem "bootstrap-sass", "3.4.1" gem "bootstrap-will_paginate", "1.0.0" gem "config" gem "faker", "2.1.2" +gem "figaro" gem "jbuilder", "~> 2.7" gem "puma", "~> 4.1" gem "rails", "~> 6.0.3", ">= 6.0.3.3" @@ -18,6 +19,9 @@ gem "sqlite3", "~> 1.4" gem "turbolinks", "~> 5" gem "webpacker", "~> 4.0" gem "will_paginate", "3.1.8" +gem "image_processing", "1.9.3" +gem "mini_magick", "4.9.5" +gem "active_storage_validations", "0.8.2" group :development, :test do gem "byebug", platforms: [:mri, :mingw, :x64_mingw] diff --git a/Gemfile.lock b/Gemfile.lock index 5e3b49c..a600a44 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -37,6 +37,8 @@ GEM erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) + active_storage_validations (0.8.2) + rails (>= 5.2.0) activejob (6.0.3.3) activesupport (= 6.0.3.3) globalid (>= 0.3.6) @@ -59,7 +61,7 @@ GEM addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) ast (2.4.1) - autoprefixer-rails (10.0.0.2) + autoprefixer-rails (10.0.1.0) execjs bcrypt (3.1.13) bindex (0.8.1) @@ -98,7 +100,7 @@ GEM concurrent-ruby (~> 1.0) dry-equalizer (0.3.0) dry-inflector (0.2.0) - dry-initializer (3.0.3) + dry-initializer (3.0.4) dry-logic (1.0.8) concurrent-ruby (~> 1.0) dry-core (~> 0.2) @@ -130,10 +132,15 @@ GEM faker (2.1.2) i18n (>= 0.8) ffi (1.13.1) + figaro (1.2.0) + thor (>= 0.14.0, < 2) globalid (0.4.2) activesupport (>= 4.2.0) i18n (1.8.5) concurrent-ruby (~> 1.0) + image_processing (1.9.3) + mini_magick (>= 4.9.5, < 5) + ruby-vips (>= 2.0.13, < 3) jaro_winkler (1.5.4) jbuilder (2.10.1) activesupport (>= 5.0.0) @@ -149,6 +156,7 @@ GEM mimemagic (~> 0.3.2) method_source (1.0.0) mimemagic (0.3.5) + mini_magick (4.9.5) mini_mime (1.0.2) mini_portile2 (2.4.0) minitest (5.14.2) @@ -215,6 +223,8 @@ GEM rack (>= 1.1) rubocop (>= 0.72.0) ruby-progressbar (1.10.1) + ruby-vips (2.0.17) + ffi (~> 1.9) rubyzip (2.3.0) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) @@ -283,6 +293,7 @@ PLATFORMS web-unknown DEPENDENCIES + active_storage_validations (= 0.8.2) bcrypt (= 3.1.13) bootsnap (>= 1.4.2) bootstrap-sass (= 3.4.1) @@ -291,8 +302,11 @@ DEPENDENCIES capybara (>= 2.15) config faker (= 2.1.2) + figaro + image_processing (= 1.9.3) jbuilder (~> 2.7) listen (~> 3.2) + mini_magick (= 4.9.5) puma (~> 4.1) rails (~> 6.0.3, >= 6.0.3.3) rails-i18n diff --git a/app/assets/stylesheets/custom.scss b/app/assets/stylesheets/custom.scss index bc8ee01..6ff0d25 100644 --- a/app/assets/stylesheets/custom.scss +++ b/app/assets/stylesheets/custom.scss @@ -146,3 +146,101 @@ input { border-bottom: 1px solid $gray-lighter; } } + +.microposts { + list-style: none; + padding: 0; + li { + padding: 10px 0; + border-top: 1px solid #e8e8e8; + } + .user { + margin-top: 5em; + padding-top: 0; + } + .content { + display: block; + margin-left: 60px; + img { + display: block; + padding: 5px 0; + } + } + + .timestamp { + color: $gray-light; + display: block; + margin-left: 60px; + } +.gravatar { + float: left; + margin-right: 10px; + width: 8%; + } +} +aside { + textarea { + height: 100px; + margin-bottom: 5px; + } +} +span.image { + margin-top: 10px; + width: 20px; + input { + border: 0; + } +} + +input[type="file"] { + display: block; + position: absolute; +} + +.gravatar { + float: left; + margin-right: 10px; +} + +.gravatar_edit { + margin-top: 15px; +} + +.stats { + overflow: auto; + margin-top: 0; + padding: 0; + a { + float: left; + padding: 0 10px; + border-left: 1px solid $gray-lighter; + color: gray; + &:first-child { + padding-left: 0; + border: 0; + } + &:hover { + text-decoration: none; + color: blue; + + } + strong { + display: block; + } + } + + .user_avatars { + overflow: auto; + margin-top: 10px; + .gravatar { + margin: 1px 1px; + } + a { + padding: 0; + } + } + + .users.follow { + padding: 0; + } +} diff --git a/app/controllers/account_activations_controller.rb b/app/controllers/account_activations_controller.rb new file mode 100644 index 0000000..3cb0aa4 --- /dev/null +++ b/app/controllers/account_activations_controller.rb @@ -0,0 +1,14 @@ +class AccountActivationsController < ApplicationController + def edit + user = User.find_by email: params[:email] + if user && !user.activated? && user.authenticated?(:activation, params[:id]) + user.activate + log_in user + flash[:success] = "Account activated!" + redirect_to user + else + flash[:danger] = "Invalid activation link" + redirect_to root_url + end + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c5f5898..edde33a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -11,4 +11,12 @@ def set_locale def default_url_options {locale: I18n.locale} end + + def logged_in_user + unless logged_in? + store_location + flash[:danger] = t("login_in.messages") + redirect_to login_url + end + end end diff --git a/app/controllers/microposts_controller.rb b/app/controllers/microposts_controller.rb new file mode 100644 index 0000000..8a8068b --- /dev/null +++ b/app/controllers/microposts_controller.rb @@ -0,0 +1,33 @@ +class MicropostsController < ApplicationController + before_action :logged_in_user, only: [:create, :destroy] + before_action :correct_user, only: :destroy + + def create + @micropost = current_user.microposts.build micropost_params + @micropost.image.attach(params[:micropost][:image]) + if @micropost.save + flash[:success] = t("micropost.messages1") + redirect_to root_url + else + @feed_items = current_user.feed.paginate(page: params[:page]) + render "static_pages/home" + end + end + + def destroy + @micropost.destroy + flash[:success] = t("micropost.messages2") + redirect_to request.referrer || root_url + end + + private + + def micropost_params + params.require(:micropost).permit :content, :picture + end + + def correct_user + @micropost = current_user.microposts.find_by id: params[:id] + redirect_to root_url unless @micropost + end +end diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb new file mode 100644 index 0000000..3ea2bbc --- /dev/null +++ b/app/controllers/password_resets_controller.rb @@ -0,0 +1,49 @@ +class PasswordResetsController < ApplicationController + before_action :get_user, only: [:edit, :update] + before_action :valid_user, only: [:edit, :update] + + def new; end + + def create + @user = User.find_by email: params[:password_reset][:email].downcase + if @user + @user.create_reset_digest + @user.send_password_reset_email + flash[:info] = "Email sent with password reset instructions" + redirect_to root_url + else + flash.now[:danger] = "Email address not found" + render :new + end + end + + def update + if params[:user][:password].empty? + @user.errors.add(:password, "can't be empty") + render 'edit' + elsif @user.update(user_params) + log_in @user + @user.update_attribute(:reset_digest, nil) + flash[:success] = "Password has been reset." + redirect_to @user + else + render :edit + end + end + + def edit; end + + private + + def get_user + @user = User.find_by email: params[:email] + end + def valid_user + return if (@user && @user.activated? && @user.authenticated?(:reset, params[:id])) + redirect_to root_url + end + + def user_params + params.require(:user).permit :password, :password_confirmation + end +end diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb new file mode 100644 index 0000000..910249a --- /dev/null +++ b/app/controllers/relationships_controller.rb @@ -0,0 +1,21 @@ +class RelationshipsController < ApplicationController + before_action :logged_in_user + + def create + @user = User.find_by(id: params[:followed_id]) + current_user.follow @user + respond_to do |format| + format.html { redirect_to @user } + format.js + end + end + + def destroy + @user = Relationship.find_by(id: params[:id]).followed + current_user.unfollow @user + respond_to do |format| + format.html { redirect_to @user } + format.js + end + end +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 01a4ae5..9e28da6 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -4,10 +4,16 @@ def new; end def create user = User.find_by(email: params[:session][:email].downcase) if user&.authenticate(params[:session][:password]) - log_in user - params[:session][:remember_me] == "1" ? remember(user) : forget(user) - remember user - redirect_back_or user + if user.activated? + log_in user + params[:session][:remember_me] == "1" ? remember(user) : forget(user) + remember user + redirect_back_or user + else + message = "Account not activated. Check your email for the activation link." + flash[:warning] = message + redirect_to root_url + end else flash.now[:danger] = t("session.flash") render :new diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb index 5268023..b0e8676 100644 --- a/app/controllers/static_pages_controller.rb +++ b/app/controllers/static_pages_controller.rb @@ -1,5 +1,10 @@ class StaticPagesController < ApplicationController - def home; end + def home + if logged_in? + @micropost = current_user.microposts.build + @feed_items = current_user.feed.paginate(page: params[:page]) + end + end def help; end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 0ed694b..67758db 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -3,8 +3,11 @@ class UsersController < ApplicationController before_action :load_user, except: %i(new index create) before_action :correct_user, only: %i(edit update) before_action :admin_user, only: :destroy + before_action :logged_in_user, only: [:index, :edit, :update, :destroy,:following, :followers] - def show; end + def show + @microposts = @user.microposts.paginate(page: params[:page]) + end def edit; end @@ -15,9 +18,9 @@ def new def create @user = User.new user_params if @user.save - flash[:success] = t ".success" - log_in @user - redirect_to @user + @user.send_activation_email + flash[:info] = t "email.messages" + redirect_to root_url else render :new end @@ -45,6 +48,21 @@ def destroy redirect_to users_url end + def following + @title = "Following" + @user = User.find_by(id: params[:id]) + @users = @user.following.paginate(page: params[:page]) + render "show_follow" + end + + def followers + @title = "Followers" + @user = User.find_by(id: params[:id]) + @users = @user.followers + .paginate(page: params[:page]) + render "show_follow" + end + private def user_params diff --git a/app/helpers/microposts_helper.rb b/app/helpers/microposts_helper.rb new file mode 100644 index 0000000..f08aad2 --- /dev/null +++ b/app/helpers/microposts_helper.rb @@ -0,0 +1,2 @@ +module MicropostsHelper +end diff --git a/app/helpers/password_resets_helper.rb b/app/helpers/password_resets_helper.rb new file mode 100644 index 0000000..0c9d96e --- /dev/null +++ b/app/helpers/password_resets_helper.rb @@ -0,0 +1,2 @@ +module PasswordResetsHelper +end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index b2505a6..ef14bb6 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -14,7 +14,8 @@ def current_user @current_user ||= User.find_by id: user_id elsif (user_id = cookies.signed[:user_id]) user = User.find_by id: user_id - if user&.authenticated?(cookies[:remember_token]) + + if user&.authenticated?(:remember, cookies[:remember_token]) log_in user @current_user = user end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 3c34c81..2dfdba2 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,4 +1,4 @@ class ApplicationMailer < ActionMailer::Base - default from: "from@example.com" + default from: "noreply@example.com" layout "mailer" end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb new file mode 100644 index 0000000..aaae448 --- /dev/null +++ b/app/mailers/user_mailer.rb @@ -0,0 +1,11 @@ +class UserMailer < ApplicationMailer + def account_activation user + @user = user + mail to: user.email, subject: "Account activation" + end + + def password_reset user + @user = user + mail to: user.email, subject: "Password reset" + end +end diff --git a/app/models/micropost.rb b/app/models/micropost.rb new file mode 100644 index 0000000..a678d26 --- /dev/null +++ b/app/models/micropost.rb @@ -0,0 +1,13 @@ +class Micropost < ApplicationRecord + belongs_to :user + # default_scope -> { order(created_at: :desc) } + scope :recent_posts, -> {order(created_at: :desc) } + has_one_attached :image + validates :user_id, presence: true + validates :content, presence: true, length: { maximum: 140 } + validates :image, content_type: { in: %w[image/jpeg image/gif image/png], message: "must be a valid image format" }, size: { less_than: 5.megabytes, message: "should be less than 5MB" } + + def display_image + image.variant(resize_to_limit: [500, 500]) + end +end diff --git a/app/models/relationship.rb b/app/models/relationship.rb new file mode 100644 index 0000000..39489b2 --- /dev/null +++ b/app/models/relationship.rb @@ -0,0 +1,7 @@ +class Relationship < ApplicationRecord + belongs_to :follower, class_name: User.name + belongs_to :followed, class_name: User.name + + validates :follower_id, presence: true + validates :followed_id, presence: true +end diff --git a/app/models/user.rb b/app/models/user.rb index 99ab078..ee393d4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,7 +1,8 @@ class User < ApplicationRecord - attr_accessor :remember_token + attr_accessor :remember_token, :activation_token, :reset_token VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.freeze - + before_save :downcase_email + before_create :create_activation_digest before_save{email.downcase!} validates :name, presence: true, length: {maximum: Settings.user.name} @@ -12,6 +13,12 @@ class User < ApplicationRecord has_secure_password validates :password, presence: true, length: {minimum: Settings.user.password}, allow_nil: true + has_many :microposts, dependent: :destroy + has_many :active_relationships, class_name: Relationship.name, foreign_key: :follower_id, dependent: :destroy + has_many :passive_relationships, class_name: Relationship.name, foreign_key: :followed_id, dependent: :destroy + has_many :following, through: :active_relationships, source: :followed + has_many :followers, through: :passive_relationships, source: :follower + def self.digest string cost = if ActiveModel::SecurePassword.min_cost BCrypt::Engine::MIN_COST @@ -34,9 +41,63 @@ def authenticated? remember_token return false if remember_digest.nil? BCrypt::Password.new(remember_digest).is_password?(remember_token) + + end + + def authenticated? attribute, token + digest = send "#{attribute}_digest" + return false if digest.nil? + + BCrypt::Password.new(digest).is_password? token + end + + def activate + update_attribute :activated, true + update_attribute :activated_at, DateTime.now + end + + def send_activation_email + UserMailer.account_activation(self).deliver_now + end + + def create_reset_digest + self.reset_token = User.new_token + update_attributes reset_digest: User.digest(reset_token), reset_sent_at: DateTime.now + end + + def send_password_reset_email + UserMailer.password_reset(self).deliver_now + end def forget update_attribute(:remember_digest, nil) end + + def feed + Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id) + end + + def follow other_user + following << other_user + end + + def unfollow other_user + following.delete other_user + end + + def following? other_user + following.include? other_user + end + + private + + def downcase_email + self.email.downcase! + end + + def create_activation_digest + self.activation_token = User.new_token + self.activation_digest = User.digest(activation_token) + end end diff --git a/app/views/microposts/_micropost.html.erb b/app/views/microposts/_micropost.html.erb new file mode 100644 index 0000000..a02d782 --- /dev/null +++ b/app/views/microposts/_micropost.html.erb @@ -0,0 +1,14 @@ +
  • + <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %> + <%= link_to micropost.user.name, micropost.user %> + + <%= micropost.content %> + <%= image_tag micropost.display_image if micropost.image.attached? %> + + + <%= t("micropost.posted") %> <%= time_ago_in_words(micropost.created_at) %> <%= t("micropost.ago") %>. + <% if current_user? micropost.user %> + <%= link_to t("micropost.button"), micropost, method: :delete, data: {confirm: t("micropost.confirm")} %> + <% end %> + +
  • diff --git a/app/views/password_resets/edit.html.erb b/app/views/password_resets/edit.html.erb new file mode 100644 index 0000000..1292fbe --- /dev/null +++ b/app/views/password_resets/edit.html.erb @@ -0,0 +1,15 @@ +<% provide(:title, "Reset password") %> +

    Reset password

    +
    +
    + <%= form_for(@user, url: password_reset_path(params[:id])) do |f| %> + <%= render 'shared/error_messages', object: f.object %> + <%= hidden_field_tag :email, @user.email %> + <%= f.label :password %> + <%= f.password_field :password, class: 'form-control' %> + <%= f.label :password_confirmation, "Confirmation" %> + <%= f.password_field :password_confirmation, class: 'form-control' %> + <%= f.submit "Update password", class: "btn btn-primary" %> + <% end %> +
    +
    diff --git a/app/views/password_resets/new.html.erb b/app/views/password_resets/new.html.erb new file mode 100644 index 0000000..4c3799c --- /dev/null +++ b/app/views/password_resets/new.html.erb @@ -0,0 +1,11 @@ +<% provide :title, "Forgot password" %> +

    Forgot password

    +
    +
    + <%= form_for :password_reset, url: password_resets_path do |f| %> + <%= f.label :email %> + <%= f.email_field :email, class: "form-control" %> + <%= f.submit "Submit", class: "btn btn-primary" %> + <% end %> +
    +
    diff --git a/app/views/relationships/create.js.erb b/app/views/relationships/create.js.erb new file mode 100644 index 0000000..9a2277b --- /dev/null +++ b/app/views/relationships/create.js.erb @@ -0,0 +1,2 @@ +$("#follow_form").html("<%= j render "users/unfollow" %>"); +$("#followers").html("<%= @user.followers.count %>"); diff --git a/app/views/relationships/destroy.js.erb b/app/views/relationships/destroy.js.erb new file mode 100644 index 0000000..27bf26b --- /dev/null +++ b/app/views/relationships/destroy.js.erb @@ -0,0 +1,2 @@ +$("#follow_form").html("<%= j render "users/follow" %>"); +$("#followers").html("<%= @user.followers.count %>"); diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index a51c500..c3415c2 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -6,6 +6,7 @@ <%= f.label :email %> <%= f.email_field :email, class: "form-control" %> <%= f.label :password, t("users.new.lable_password") %> + <%= link_to "(forgot password)", new_password_reset_path %> <%= f.password_field :password, class: "form-control" %> <%= f.label :remember_me, class: "checkbox inline" do %> <%= f.check_box :remember_me %> diff --git a/app/views/shared/_error_messages.html.erb b/app/views/shared/_error_messages.html.erb index 6ae0a98..10fa4c8 100644 --- a/app/views/shared/_error_messages.html.erb +++ b/app/views/shared/_error_messages.html.erb @@ -1,10 +1,10 @@ -<% if @user.errors.any? %> +<% if object.errors.any? %>
    - <%= t("users.messages") %> <%= pluralize(@user.errors.count, t("users.error")) %>. + <%= t("users.messages") %> <%= pluralize object.errors.count, t("users.error") %>.
    diff --git a/app/views/shared/_feed.html.erb b/app/views/shared/_feed.html.erb new file mode 100644 index 0000000..f15a53c --- /dev/null +++ b/app/views/shared/_feed.html.erb @@ -0,0 +1,6 @@ +<% if @feed_items.any? %> +
      + <%= render @feed_items %> +
    + <%= will_paginate @feed_items, params: { controller: :static_pages, action: :home } %> +<% end %> diff --git a/app/views/shared/_micropost_form.html.erb b/app/views/shared/_micropost_form.html.erb new file mode 100644 index 0000000..3f829fe --- /dev/null +++ b/app/views/shared/_micropost_form.html.erb @@ -0,0 +1,19 @@ +<%= form_for(@micropost, html: { multipart: true }) do |f| %> + <%= render "shared/error_messages", object: f.object %> +
    + <%= f.text_area :content, placeholder: t("micropost.compose_new") %> +
    + <%= f.submit t("micropost.post"), class: "btn btn-primary" %> + + <%= f.file_field :image %> + +<% end %> + + diff --git a/app/views/shared/_stats.html.erb b/app/views/shared/_stats.html.erb new file mode 100644 index 0000000..c597a87 --- /dev/null +++ b/app/views/shared/_stats.html.erb @@ -0,0 +1,15 @@ +<% @user ||= current_user %> +
    + + + <%= @user.following.count %> + + <%= t("follow.following") %> + + + + <%= @user.followers.count %> + + <%= t("follow.followers") %> + +
    diff --git a/app/views/shared/_user_info.html.erb b/app/views/shared/_user_info.html.erb new file mode 100644 index 0000000..b9c43ba --- /dev/null +++ b/app/views/shared/_user_info.html.erb @@ -0,0 +1,4 @@ +<%= link_to gravatar_for(current_user, size: 50), current_user %> +

    <%= current_user.name %>

    +<%= link_to t("micropost.title"), current_user %> +<%= pluralize(current_user.microposts.count, "micropost") %> diff --git a/app/views/static_pages/home.html.erb b/app/views/static_pages/home.html.erb index 8431798..060a4db 100644 --- a/app/views/static_pages/home.html.erb +++ b/app/views/static_pages/home.html.erb @@ -1,4 +1,22 @@ -<% provide :title, t("home") %> +<% if logged_in? %> +
    + +
    +

    Micropost Feed

    + <%= render "shared/feed" %> +
    +
    +<% else %>

    <%= t("title") %>

    @@ -8,3 +26,4 @@

    <%= link_to t("static_pages.home.button"), '#', class: "btn btn-lg btn-primary" %>
    +<% end %> diff --git a/app/views/user_mailer/account_activation.html.erb b/app/views/user_mailer/account_activation.html.erb new file mode 100644 index 0000000..f64fe84 --- /dev/null +++ b/app/views/user_mailer/account_activation.html.erb @@ -0,0 +1,8 @@ +

    <%= t("logo") %>

    +

    Hi <%= @user.name %>,

    +

    + <%= t("email.sendemail")%> + <%= t("email.account")%> +

    +<%= link_to t("email.activate"), +edit_account_activation_url(id: @user.activation_token, email: @user.email) %> diff --git a/app/views/user_mailer/account_activation.text.erb b/app/views/user_mailer/account_activation.text.erb new file mode 100644 index 0000000..4f396b4 --- /dev/null +++ b/app/views/user_mailer/account_activation.text.erb @@ -0,0 +1,7 @@ +Hi <%= @user.name %>, + +<%= t("email.sendemail")%> +<%= t("email.account")%> + +<%= edit_account_activation_url(id:@user.activation_token, email: +@user.email) %> diff --git a/app/views/user_mailer/password_reset.html.erb b/app/views/user_mailer/password_reset.html.erb new file mode 100644 index 0000000..f65dbb0 --- /dev/null +++ b/app/views/user_mailer/password_reset.html.erb @@ -0,0 +1,7 @@ +

    Password reset

    +

    To reset your password click the link below:

    +<%= link_to "Reset password", edit_password_reset_url(@user.reset_token, email: @user.email) %> +

    This link will expire in two hours.

    +

    +If you did not request your password to be reset, please ignore this email and your password will stay as it is. +

    diff --git a/app/views/user_mailer/password_reset.text.erb b/app/views/user_mailer/password_reset.text.erb new file mode 100644 index 0000000..6d29feb --- /dev/null +++ b/app/views/user_mailer/password_reset.text.erb @@ -0,0 +1,6 @@ +To reset your password click the link below: + +<%= edit_password_reset_url @user.reset_token, email: @user.email %> + +This link will expire in two hours. +If you did not request your password to be reset, please ignore this email and your password will stay as it is. diff --git a/app/views/users/_follow.html.erb b/app/views/users/_follow.html.erb new file mode 100644 index 0000000..6ad39b9 --- /dev/null +++ b/app/views/users/_follow.html.erb @@ -0,0 +1,4 @@ +<%= form_for(current_user.active_relationships.build, remote: true) do |f| %> +
    <%= hidden_field_tag :followed_id, @user.id %>
    + <%= f.submit t("follow.button_follow"), class: "btn btn-primary" %> +<% end %> diff --git a/app/views/users/_follow_form.html.erb b/app/views/users/_follow_form.html.erb new file mode 100644 index 0000000..d4221b1 --- /dev/null +++ b/app/views/users/_follow_form.html.erb @@ -0,0 +1,9 @@ +<% unless current_user?(@user) %> +
    + <% if current_user.following?(@user) %> + <%= render "unfollow" %> + <% else %> + <%= render "follow" %> + <% end %> +
    +<% end %> diff --git a/app/views/users/_form.html.erb b/app/views/users/_form.html.erb index 9021e90..6f19a6e 100644 --- a/app/views/users/_form.html.erb +++ b/app/views/users/_form.html.erb @@ -1,5 +1,5 @@ -<%= form_for(@user) do |f| %> - <%= render "shared/error_messages", object: @user %> +<%= form_for (@user) do |f| %> + <%= render 'shared/error_messages', object: f.object %> <%= f.label :name, t("users.new.lable_name") %> <%= f.text_field :name, class: "form-control" %> <%= f.label :email %> diff --git a/app/views/users/_unfollow.html.erb b/app/views/users/_unfollow.html.erb new file mode 100644 index 0000000..6e4dbc6 --- /dev/null +++ b/app/views/users/_unfollow.html.erb @@ -0,0 +1,3 @@ +<%= form_for(current_user.active_relationships.find_by(followed_id: @user.id), html: { method: :delete , remote: true}) do |f| %> + <%= f.submit t("follow.unfollow"), class: "btn" %> +<% end %> diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 911cfc8..31fd762 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,4 +1,4 @@ -<% provide(:title, 'All users') %> +<% provide(:title, t("users.new.all_users")) %>

    <%= t("session.title") %>

    <%= will_paginate %>