Commit 96eb85ed by Ngô Trung Hưng

Merge branch 'admin' into 'master'

create function admin

See merge request !16
parents 897ec388 f18b0d89
Pipeline #1116 canceled with stages
in 0 seconds
...@@ -322,9 +322,6 @@ GEM ...@@ -322,9 +322,6 @@ GEM
actionpack (>= 4.0) actionpack (>= 4.0)
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sshkit (1.21.0)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
therubyracer (0.12.3) therubyracer (0.12.3)
libv8 (~> 3.16.14.15) libv8 (~> 3.16.14.15)
ref ref
......
// Place all the styles related to the admin controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
.new_admin {
width: 100%;
}
@mixin admin_select {
margin-top: 10px;
border: 1px solid #ced4da;
border-radius: 0.25rem;
height: 40px;
padding: 0.375rem 0.75rem 0.375rem 0.6rem;
}
@mixin admin_select__child {
border: none;
width: 100%;
height: 100%;
background-color: transparent;
font-weight: 400;
font-size: 1rem;
color: #495057;
cursor: pointer;
&:focus {
outline: none;
}
}
.admin_box_search__filter_city_id, .admin_box_search__filter_industry_id {
@include admin_select()
}
.admin_box_search__filter_date {
@include admin_select();
border: none !important;
padding-left: 0 !important;
padding-right: 0 !important;
margin-top: 0px;
select {
@include admin_select();
margin-top: 0px;
&:focus {
outline: none;
}
}
}
.admin_box_search__filter_date__past_time, .admin_box_search__filter_date__current_time {
width: 100%;
text-align: center;
}
.admin_box_search__btn {
margin-top: 10px;
}
.admin_box_search__download {
width: 100%;
text-align: right;
margin-top: 10px;
}
.symbol_to {
font-size: 26px;
font-weight: 600;
}
.btn-admin-search {
width: 100%;
}
#apply_city_id, #apply_industry_id {
@include admin_select__child()
}
.block_result_applied {
margin-top: 100px;
}
.card {
margin-bottom: 10px !important;
}
.job_name.big_w {
font-size: 18px !important;
}
.info__name {
margin-bottom: 0px !important;
}
.card {
background-color: antiquewhite !important;
&:hover {
box-shadow: 0px 0px 5px 1px #3e3712;
transition: 0.3s;
}
}
.avt_user {
text-align: center;
}
.img_avt_user {
width: 170px;
height: 170px;
border: 2px solid #666;
border-radius: 50%;
}
.content_user {
font-family: 'Raleway', sans-serif;
}
.h_user_info {
font-size: 30px;
}
.total_count_applied_job {
font-size: 18px;
font-weight: bold;
}
@media only screen and (max-width: 768px) {
.block_result_applied {
padding-top: 60px;
}
}
...@@ -731,7 +731,7 @@ $main-color: #23303D; ...@@ -731,7 +731,7 @@ $main-color: #23303D;
} }
.job_name { .job_name {
font-size: 16px; font-size: 16px;
line-height: 14px; // line-height: 14px;
font-weight: 600; font-weight: 600;
color: #d41323; color: #d41323;
overflow: hidden; overflow: hidden;
......
# frozen_string_literal: true
# Admin controller
class Admin::AdminController < ApplicationController
before_action :authenticate_admin!, only: %s(index search export_csv)
before_action :load_data_dropdown
include InitApply
# user input in url 'localhost:3000/admin' if admin signed redirect to applies page else admin login page
def routing
return redirect_to new_admin_session_path unless admin_signed_in?
redirect_to applies_index_path
end
def index
@applied = AppliedJob.includes(:job).all_result.page(params[:page]).per(6)
@apply = apply
end
def search
return redirect_to applies_index_path if params[:apply].blank?
return export_csv(result_for(params[:apply])) if params[:export_csv].present?
@applied = result_for(params[:apply]).includes(:job).page(params[:page]).per(6)
@city_id = params[:apply][:city_id]
@industry_id = params[:apply][:industry_id]
@params_date = params[:apply]
@apply = apply
render :index
end
def load_data_dropdown
@industries = Industry.order(name: :asc)
@cities = City.select(:id, :name)
end
private
def result_for(params)
Searches.new(params).search
end
def export_csv(result)
csv = ExportCsv.new(result, AppliedJob::CSV_ATTR)
send_data csv.perform, filename: "#{Time.now}applied.csv"
end
end
...@@ -16,6 +16,11 @@ class ApplicationController < ActionController::Base ...@@ -16,6 +16,11 @@ class ApplicationController < ActionController::Base
{ locale: I18n.locale } { locale: I18n.locale }
end end
def after_sign_in_path_for(resource)
return applies_path if resource.model_name == Admin.name
stored_location_for(resource) || root_path
end
protected protected
def configure_permitted_parameters def configure_permitted_parameters
......
# frozen_string_literal: true
module InitApply
def apply
Apply.new(applied_params)
end
private
def applied_params
return {} if params[:apply].blank?
params.require(:apply).permit(:email, :city_id, :industry_id)
end
end
...@@ -10,7 +10,4 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -10,7 +10,4 @@ class RegistrationsController < Devise::RegistrationsController
my_page_path my_page_path
end end
def after_sign_in_path_for(resource)
stored_location_for(resource) || root_path
end
end end
...@@ -9,6 +9,12 @@ class UsersController < ApplicationController ...@@ -9,6 +9,12 @@ class UsersController < ApplicationController
def my_page; end def my_page; end
def personal_page
@user = User.find_by_id params[:user_id]
return render 'error/page_not_found' if @user.blank?
@jobs = @user.applied_jobs.includes(:job).order(created_at: :desc).page(params[:page]).per(20)
end
def set_lang def set_lang
current_user.update_current_language(params[:lang]) if user_signed_in? current_user.update_current_language(params[:lang]) if user_signed_in?
redirect_to '/' redirect_to '/'
......
...@@ -5,4 +5,8 @@ class AppliedJobDecorator < Draper::Decorator ...@@ -5,4 +5,8 @@ class AppliedJobDecorator < Draper::Decorator
def applied_at def applied_at
object.created_at.localtime.strftime('%H:%M %d - %m - %Y') object.created_at.localtime.strftime('%H:%M %d - %m - %Y')
end end
def applied_at_in_admin_page
object.created_at.localtime.strftime('%d - %m - %Y')
end
end end
# frozen_string_literal: true
# Decorator
class UserDecorator < Draper::Decorator
delegate_all
def join_at
created_at.strftime('%d - %m - %Y')
end
end
\ No newline at end of file
# frozen_string_literal: true
class Apply
include ActiveModel::Model
attr_accessor :email, :city_id, :industry_id, :past_time, :current_time
def self.selected(params)
params.blank? ? '*' : params
end
def self.selected_date(params)
params.present? ? {
selected_past_year: params['past_time(1i)'].to_i,
selected_past_month: params['past_time(2i)'].to_i,
selected_past_day: params['past_time(3i)'].to_i,
selected_current_year: params['current_time(1i)'].to_i,
selected_current_month: params['current_time(2i)'].to_i,
selected_current_day: params['current_time(3i)'].to_i
} :
{
selected_past_year: Date.current.year,
selected_current_year: Date.current.year,
selected_past_month: Date.current.month,
selected_current_month: Date.current.month,
selected_past_day: Date.current.day,
selected_current_day: Date.current.day
}
end
end
module AdminHelper
end
...@@ -25,4 +25,8 @@ module ApplicationHelper ...@@ -25,4 +25,8 @@ module ApplicationHelper
obj.errors.full_messages.each { |mess| errors << "#{mess}<br>" } obj.errors.full_messages.each { |mess| errors << "#{mess}<br>" }
flash[:error] = errors.join('<br>').html_safe flash[:error] = errors.join('<br>').html_safe
end end
def is_url_admin?
request.url.include?('admin/login')
end
end end
class Admin < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
end
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
# Description/Explanation of Person class # Description/Explanation of Person class
class AppliedJob < ApplicationRecord class AppliedJob < ApplicationRecord
CSV_ATTR = %w[job_id name email cv created_at].freeze
scope :all_result, -> { order(created_at: :desc) }
mount_uploader :cv, CvUploader mount_uploader :cv, CvUploader
belongs_to :user belongs_to :user
belongs_to :job belongs_to :job
......
# frozen_string_literal: true
class Searches
attr_accessor :params
def initialize(params)
@params = params
end
def search
return AppliedJob.none unless get_data_fillter
return get_data_fillter if [params[:city_id], params[:industry_id]].all?(&:blank?)
ids_job_by_city = params[:city_id].present? ? CityJob.where(city_id: params[:city_id]).pluck(:job_id) : []
ids_job_by_industry = params[:industry_id].present? ? IndustryJob.where(industry_id: params[:industry_id]).pluck(:job_id) : []
intersection = [ids_job_by_city, ids_job_by_industry].any?(&:blank?) ? ids_job_by_city | ids_job_by_industry : ids_job_by_city & ids_job_by_industry
return AppliedJob.none if intersection.blank?
get_data_fillter.where(job_id: get_data_fillter.pluck(:job_id) & intersection)
end
def get_data_fillter
past_time = DateTime.new(params['past_time(1i)'].to_i, params['past_time(2i)'].to_i, params['past_time(3i)'].to_i)
current_time = DateTime.new(params['current_time(1i)'].to_i, params['current_time(2i)'].to_i, params['current_time(3i)'].to_i)
return AppliedJob.none if past_time > current_time || current_time < past_time || [past_time, current_time].any?(&:blank?)
result = AppliedJob.where(created_at: past_time...current_time + 1.days)
params[:email].present? ? result.where(email: params[:email]) : result
end
end
<%= render 'layouts/padding' %>
<div class="box_search_candidate">
<div class="box_text_five_jobs">
<span><%= t('pages.index.admin_applied') %></span>
</div>
<div class="container">
<%= form_for @apply, enforce_utf8: false, method: :get do |f| %>
<div class="admin_box_search">
<div class="admin_box_search__filter_string">
<div class="row">
<div class="col-lg-12">
<%= f.search_field :email, placeholder: 'Email', class: 'form-control' %>
</div>
</div>
</div>
<div class="admin_box_search__filter_id">
<div class="row">
<div class="col-lg-6">
<div class="admin_box_search__filter_city_id">
<%= f.select :city_id, options_from_collection_for_select(@cities, 'id', 'name', Apply.selected(@city_id)), include_blank: t('pages.banner.all_locations') %>
</div>
</div>
<div class="col-lg-6">
<div class="admin_box_search__filter_industry_id">
<%= f.select :industry_id, options_from_collection_for_select(@industries, 'id', 'name', Apply.selected(@industry_id)), include_blank: t('pages.banner.all_industries') %>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="admin_box_search__filter_date">
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="admin_box_search__filter_date__past_time">
<% date = Apply.selected_date(@params_date) %>
<%= f.date_select :past_time, order: [:year, :month, :day], start_year: Time.now.year - 10, end_year: Time.now.year, selected: { day: date[:selected_past_day], month: date[:selected_past_month], year: date[:selected_past_year] } %>
</div>
</div>
<div class="col-lg-6 col-md-6">
<div class="admin_box_search__filter_date__current_time">
<%= f.date_select :current_time, order: [:year, :month, :day], start_year: Time.now.year - 10, end_year: Time.now.year, selected: { day: date[:selected_current_day], month: date[:selected_current_month], year: date[:selected_current_year] } %>
</div>
</div>
<div class="col-lg-4 col-md-4">
<div class="admin_box_search__btn">
<%= f.submit t('admin.filter'), class: 'btn btn-success btn-admin-search', data: { disable_with: false }%>
</div>
</div>
<div class="col-lg-4 col-md-4">
<div class="admin_box_search__btn">
<%= link_to t('admin.show_all'), applies_index_path, class: 'btn btn-info btn-admin-search' %>
</div>
</div>
<div class="col-lg-4 col-md-4">
<div class="admin_box_search__btn">
<%= f.submit t('admin.dl'), name: 'export_csv', class: 'btn btn-primary btn-admin-search btn-export_csv', data: { disable_with: false } %>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<% end %>
</div>
</div>
<div class="container">
<div class="block_result_applied"><hr>
<% if @applied.present? %>
<span class="total_count_applied_job"> <%= t('admin.has_record', result_count: @applied.total_count) %></span><hr>
<div class="row">
<%= render partial: 'card_candidate', collection: @applied, as: :data %>
<% else %>
<%= t('admin.no_record') %>
<% end %>
</div>
</div>
</div>
<%= render 'shared/paginate', data: @applied, as: :data %>
<div class="col-lg-6 col-sm-12">
<div class="card">
<div class="card-body">
<div class="lol">
<%= link_to data.job.name, detail_job_path(id: data.job_id), class: 'job_name big_w' %>
</div>
<span class="info__name"><b><%= t('pages.mypage.name')%></b></span>: <%= link_to data.name, personal_page_path(user_id: data.user_id), class: 'info__name' %>
<div class="lol">
<p class="info__name"><b><%= t('pages.mypage.cv') %>: <%= link_to data.cv.identifier, data.cv.url, target: '_blank', class: 'link_ct pdf' %></b></p>
</div>
<p class="info__name"><b><%= t('pages.mypage.email') %>: <%= data.email %></b></p>
<p class="info__name"><b><%= t('pages.mypage.applied_at') %><%= data.decorate.applied_at_in_admin_page %></b></p>
</div>
</div>
</div>
<% provide(:title, 'Admin') %>
<%= render 'box_filter' %>
<%= render 'shared/scroll_top' %>
<%= render 'box_result_applied' %>
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="col-lg-4"> <div class="col-lg-4">
<div class="loc"> <div class="loc">
<h5 class="box_info_location"><i class="fas fa-map-marker-alt"></i> <h5 class="box_info_location"><i class="fas fa-map-marker-alt"></i>
<%= data.job.cities.map(&:name).join(' | ') %> <%= data.job.cities.pluck(:name).join(' | ') %>
</h5> </h5>
</div> </div>
</div> </div>
......
<% provide(:title, 'Sign in') %> <% provide(:title, is_url_admin? ? 'Admin' : 'Sign in') %>
<div class="container"> <div class="container">
<div class="box_form"> <div class="box_form">
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
<h2 style="text-align: center"><%= t('devise.title_signin') %></h2><hr> <h2 style="text-align: center"><%= is_url_admin? ? 'Admin' : t('devise.title_signin') %></h2><hr>
</div> </div>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="row"> <div class="row">
...@@ -43,9 +43,11 @@ ...@@ -43,9 +43,11 @@
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
<%= f.submit t('devise.title_signin'), class: 'btn btn-info btn-info-custom' %> <%= f.submit t('devise.title_signin'), class: 'btn btn-info btn-info-custom' %>
<div style="text-align: center; margin-top: 10px"> <% if !is_url_admin? %>
<%= link_to t('devise.ask_forget_password'), new_password_path(resource_name), class: 'link_ct' %> <div style="text-align: center; margin-top: 10px">
</div> <%= link_to t('devise.ask_forget_password'), new_password_path(resource_name), class: 'link_ct'%>
</div>
<% end %>
</div> </div>
</div><br> </div><br>
<% end %> <% end %>
......
...@@ -7,45 +7,55 @@ ...@@ -7,45 +7,55 @@
<label for="mobile-nav" class="lbn-nav">&#9776</label> <label for="mobile-nav" class="lbn-nav">&#9776</label>
<label for="mobile-nav" class="overlay"></label> <label for="mobile-nav" class="overlay"></label>
<div class = "override"></div> <div class = "override"></div>
<div class="header_top_menu_right"> <div class="header_top_menu_right">
<ul class="list_menu_header_right"> <ul class="list_menu_header_right">
<li class="list_item_menu_header_right"> <% if admin_signed_in? %>
<%= link_to_if(!user_signed_in?, t('pages.index.favorite'), favorite_index_path, class: 'link_item_menu_header_right') do <li class="list_item_menu_header_right">
link_to "(#{current_user.favorites.count}) #{t('pages.index.favorite')}", favorite_index_path, class: 'link_item_menu_header_right number_favorite' <%= link_to t('pages.index.signout'), destroy_user_session_path, method: :delete, class: 'link_item_menu_header_right'%>
end %> </li>
</li> <li class="list_item_menu_header_right">
<li class="list_item_menu_header_right"> <span class="link_item_menu_header_right"><i class="far fa-question-circle"></i></span>
<%= link_to t('pages.index.history'), list_histories_path, class: 'link_item_menu_header_right' %> </li>
</li> <% else %>
<li class="list_item_menu_header_right"> <li class="list_item_menu_header_right">
<%= link_to_if(user_signed_in?, t('pages.index.mypage'), my_page_path, class: 'link_item_menu_header_right') do <%= link_to_if(!user_signed_in?, t('pages.index.favorite'), favorite_index_path, class: 'link_item_menu_header_right') do
link_to t('pages.index.signin'), new_user_session_path, class: 'link_item_menu_header_right' link_to "(#{current_user.favorites.count}) #{t('pages.index.favorite')}", favorite_index_path, class: 'link_item_menu_header_right number_favorite'
end %> end %>
</li> </li>
<li class="list_item_menu_header_right"> <li class="list_item_menu_header_right">
<%= link_to_if(user_signed_in?, t('pages.index.signout'), destroy_user_session_path, method: :delete, class: 'link_item_menu_header_right') do <%= link_to t('pages.index.history'), list_histories_path, class: 'link_item_menu_header_right' %>
link_to t('pages.index.register'), new_user_registration_path, class: 'link_item_menu_header_right' </li>
end %> <li class="list_item_menu_header_right">
</li> <%= link_to_if(user_signed_in?, t('pages.index.mypage'), my_page_path, class: 'link_item_menu_header_right') do
<li class="list_item_menu_header_right have_menu"> link_to t('pages.index.signin'), new_user_session_path, class: 'link_item_menu_header_right'
<%= link_to t('pages.index.language'), '#', class: 'link_item_menu_header_right' %> end %>
<div class="menu_hover"> </li>
<ul> <li class="list_item_menu_header_right">
<li> <%= link_to_if(user_signed_in?, t('pages.index.signout'), destroy_user_session_path, method: :delete, class: 'link_item_menu_header_right') do
<%= image_tag('flagusa.png', class: 'header_img_flag')%> link_to t('pages.index.register'), new_user_registration_path, class: 'link_item_menu_header_right'
<%= link_to_if(user_signed_in?, t('pages.index.en'), set_lang_path(lang: 'en'), class: 'link_ct apply_job') do end %>
link_to t('pages.index.en'), {locale: 'en'}, {class: 'link_ct apply_job'} </li>
end %> <li class="list_item_menu_header_right have_menu">
</li> <%= link_to t('pages.index.language'), '#', class: 'link_item_menu_header_right' %>
<li> <div class="menu_hover">
<%= image_tag('flagvn.png', class: 'header_img_flag')%> <ul>
<%= link_to_if(user_signed_in?, t('pages.index.vi'), set_lang_path(lang: 'vi'), class: 'link_ct apply_job') do <li>
link_to t('pages.index.vi'), {locale: 'vi'}, {class: 'link_ct apply_job'} <%= image_tag('flagusa.png', class: 'header_img_flag')%>
end %> <%= link_to_if(user_signed_in?, t('pages.index.en'), set_lang_path(lang: 'en'), class: 'link_ct apply_job') do
</li> link_to t('pages.index.en'), {locale: 'en'}, {class: 'link_ct apply_job'}
</ul> end %>
</div> </li>
</li> <li>
<%= image_tag('flagvn.png', class: 'header_img_flag')%>
<%= link_to_if(user_signed_in?, t('pages.index.vi'), set_lang_path(lang: 'vi'), class: 'link_ct apply_job') do
link_to t('pages.index.vi'), {locale: 'vi'}, {class: 'link_ct apply_job'}
end %>
</li>
</ul>
</div>
</li>
<% end %>
</ul> </ul>
</div> </div>
<%# mobile %> <%# mobile %>
...@@ -54,36 +64,41 @@ ...@@ -54,36 +64,41 @@
<%= link_to image_tag('avatar.png', alt: 'avatar', class: 'avatar_manu'), '#' %> <%= link_to image_tag('avatar.png', alt: 'avatar', class: 'avatar_manu'), '#' %>
<div class = "menu_mobile_vertical"> <div class = "menu_mobile_vertical">
<ul class = "list_menu_mobile_vertical"> <ul class = "list_menu_mobile_vertical">
<li class = "item_menu_mobile_vertical"> <% if admin_signed_in? %>
<%= link_to_if(!user_signed_in?, t('pages.index.favorite'), favorite_index_path, class: 'link_item_menu_mobile') do
link_to "(#{current_user.favorites.count}) #{t('pages.index.favorite')}", favorite_index_path, class: 'link_item_menu_mobile number_favorite'
end %>
</li>
<li class = "item_menu_mobile_vertical">
<%= link_to t('pages.index.history'), list_histories_path, class: 'link_item_menu_mobile' %>
</li>
<li class="item_menu_mobile_vertical">
<%= link_to_if(user_signed_in?, t('pages.index.mypage'), my_page_path, class: 'link_item_menu_mobile') do
link_to t('pages.index.signin'), new_user_session_path, class: 'link_item_menu_mobile'
end %>
</li>
<li class="item_menu_mobile_vertical"> <li class="item_menu_mobile_vertical">
<%= link_to_if(user_signed_in?, t('pages.index.signout'), destroy_user_session_path, method: :delete, class: 'link_item_menu_mobile') do <%= link_to t('pages.index.signout'), destroy_user_session_path, method: :delete, class: 'link_item_menu_mobile'%>
link_to t('pages.index.register'), new_user_registration_path, class: 'link_item_menu_mobile' <% else %>
end %> <li class = "item_menu_mobile_vertical">
</li><hr style="width: 60%; background-color: #999;"> <%= link_to_if(!user_signed_in?, t('pages.index.favorite'), favorite_index_path, class: 'link_item_menu_mobile') do
<li class="item_menu_mobile_vertical"> link_to "(#{current_user.favorites.count}) #{t('pages.index.favorite')}", favorite_index_path, class: 'link_item_menu_mobile number_favorite'
<span class="link_item_menu_mobile custom"><%= t('pages.index.language') %></span> end %>
</li> </li>
<li class="item_menu_mobile_vertical"> <li class = "item_menu_mobile_vertical">
<%= link_to_if(user_signed_in?, t('pages.index.en'), set_lang_path(lang: 'en'), class: 'link_item_menu_mobile') do <%= link_to t('pages.index.history'), list_histories_path, class: 'link_item_menu_mobile' %>
link_to t('pages.index.en'), {locale: 'en'}, {class: 'link_item_menu_mobile'} </li>
end %> <li class="item_menu_mobile_vertical">
<span style="color: #999;"> |</span> <%= link_to_if(user_signed_in?, t('pages.index.mypage'), my_page_path, class: 'link_item_menu_mobile') do
<%= link_to_if(user_signed_in?, t('pages.index.vi'), set_lang_path(lang: 'vi'), class: 'link_item_menu_mobile') do link_to t('pages.index.signin'), new_user_session_path, class: 'link_item_menu_mobile'
link_to t('pages.index.vi'), {locale: 'vi'}, {class: 'link_item_menu_mobile'} end %>
end %> </li>
</li> <li class="item_menu_mobile_vertical">
<%= link_to_if(user_signed_in?, t('pages.index.signout'), destroy_user_session_path, method: :delete, class: 'link_item_menu_mobile') do
link_to t('pages.index.register'), new_user_registration_path, class: 'link_item_menu_mobile'
end %>
</li><hr style="width: 60%; background-color: #999;">
<li class="item_menu_mobile_vertical">
<span class="link_item_menu_mobile custom"><%= t('pages.index.language') %></span>
</li>
<li class="item_menu_mobile_vertical">
<%= link_to_if(user_signed_in?, t('pages.index.en'), set_lang_path(lang: 'en'), class: 'link_item_menu_mobile') do
link_to t('pages.index.en'), {locale: 'en'}, {class: 'link_item_menu_mobile'}
end %>
<span style="color: #999;"> |</span>
<%= link_to_if(user_signed_in?, t('pages.index.vi'), set_lang_path(lang: 'vi'), class: 'link_item_menu_mobile') do
link_to t('pages.index.vi'), {locale: 'vi'}, {class: 'link_item_menu_mobile'}
end %>
</li>
<% end %>
</ul> </ul>
</div> </div>
<div> <div>
......
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="breadcrumb_total_search_pagination_jobs">
<div class="pagination_jobs">
<div class="paginator">
<%= paginate data %>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
<% provide(:title, 'Trang cá nhân') %>
<hr>
<div class="container">
<div class="row">
<div class="col-lg-2">
<div class="avt_user">
<%= image_tag 'avt', class: 'img_avt_user'%>
</div>
</div>
<div class="col-lg-10">
<div class="content_user">
<h5 class="h_user_info"><%= t('profile.title') %><h5><hr>
<span><b><%= t('profile.name') %></b></span><span class="user_info"><%= @user.name %></span><br>
<span><b><%= t('profile.email') %></b></span><span class="user_info"><%= @user.email %></span><br>
<span><b><%= t('profile.join_at') %></b></span><span class="user_info"><%= @user.decorate.join_at %></span>
</div><hr>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-12">
<hr>
<div class="box_text_five_jobs">
<span><%= t('apply_job.title') %></span>
</div>
<hr>
</div>
<% if @jobs.blank? %>
<div class="col-lg-12">
<div class="breadcrumb_total_search">
<span class="breadcrumb-item active">
<%= t('apply_job.no_record') %>
</span>
</div>
</div>
<% else %>
<%= render partial: 'apply_job/block_info_job', collection: @jobs, as: :data %>
<% end %>
</div>
</div>
<%= render 'shared/paginate', data: @jobs, as: :data %>
<%= render 'shared/scroll_top' %>
...@@ -16,7 +16,8 @@ module Venjob ...@@ -16,7 +16,8 @@ module Venjob
# i18n # i18n
config.i18n.available_locales = [:en, :vi] config.i18n.available_locales = [:en, :vi]
config.i18n.default_locale = :vi config.i18n.default_locale = :vi
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')] config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
# Settings in config/environments/* take precedence over those specified here. # Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers # Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading # -- all .rb files in that directory are automatically loaded after loading
......
...@@ -29,9 +29,9 @@ Rails.application.configure do ...@@ -29,9 +29,9 @@ Rails.application.configure do
if Rails.root.join('tmp', 'caching-dev.txt').exist? if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true config.action_controller.perform_caching = true
config.cache_store = :memory_store config.cache_store = :memory_store, { size: 64.megabytes }
config.public_file_server.headers = { config.public_file_server.headers = {
'Cache-Control' => "public, max-age=#{2.days.to_i}" 'Cache-Control' => "public, max-age=#{1.days.to_i}"
} }
else else
config.action_controller.perform_caching = false config.action_controller.perform_caching = false
......
...@@ -29,6 +29,7 @@ en: ...@@ -29,6 +29,7 @@ en:
en: 'English' en: 'English'
setting: 'Settings' setting: 'Settings'
applied_at: 'Applied_at' applied_at: 'Applied_at'
admin_applied: 'Applied Jobs'
banner: banner:
slogan: 'VENJOB HUMAN RESOURCE PLATFORM' slogan: 'VENJOB HUMAN RESOURCE PLATFORM'
slogan_2: 'Instantly discover the best jobs on VenJob' slogan_2: 'Instantly discover the best jobs on VenJob'
...@@ -73,6 +74,7 @@ en: ...@@ -73,6 +74,7 @@ en:
myjob: 'My jobs' myjob: 'My jobs'
nofile: 'Please upload your cv' nofile: 'Please upload your cv'
you_are_using: "You're using:" you_are_using: "You're using:"
applied_at: 'Applied at: '
errors: errors:
back_to_home: "Let's go back to the homepage" back_to_home: "Let's go back to the homepage"
error_500_1: 'There are some errors in this path' error_500_1: 'There are some errors in this path'
...@@ -149,6 +151,24 @@ en: ...@@ -149,6 +151,24 @@ en:
user_id: '' user_id: ''
favorite: favorite:
user_id: '' user_id: ''
admin:
search: 'Search'
dl: 'Download CSV'
show_all: 'Show All'
filter: 'Filter'
no_record: 'No record'
has_record: 'Have %{result_count} result'
profile:
title: 'Profile'
name: 'Name: '
email: 'Email: '
join_at: 'Join at: '
header_csv:
job_id: 'Job name'
name: 'Name candidate'
email: 'Email'
cv: 'CV Path'
created_at: 'Applied at'
views: views:
pagination: pagination:
last: 'Last' last: 'Last'
......
...@@ -29,6 +29,7 @@ vi: ...@@ -29,6 +29,7 @@ vi:
en: 'Tiếng Anh' en: 'Tiếng Anh'
setting: 'Cài đặt' setting: 'Cài đặt'
applied_at: 'Ứng tuyển lúc: ' applied_at: 'Ứng tuyển lúc: '
admin_applied: 'Danh sách thí sinh ứng tuyển'
banner: banner:
slogan: 'NỀN TẢNG TUYỂN DỤNG NHÂN SỰ VENJOB' slogan: 'NỀN TẢNG TUYỂN DỤNG NHÂN SỰ VENJOB'
slogan_2: 'Khám phá ngay những việc làm tốt nhất trên VenJob' slogan_2: 'Khám phá ngay những việc làm tốt nhất trên VenJob'
...@@ -73,6 +74,7 @@ vi: ...@@ -73,6 +74,7 @@ vi:
myjob: 'Công việc của tôi' myjob: 'Công việc của tôi'
nofile: 'Vui lòng tải lên cv của bạn' nofile: 'Vui lòng tải lên cv của bạn'
you_are_using: 'Bạn đang sử dụng:' you_are_using: 'Bạn đang sử dụng:'
applied_at: 'Ứng tuyển lúc: '
errors: errors:
back_to_home: 'Cùng mình quay lại trang chủ nhé' back_to_home: 'Cùng mình quay lại trang chủ nhé'
error_500_1: ' vài lỗi trong đường dẫn này' error_500_1: ' vài lỗi trong đường dẫn này'
...@@ -149,8 +151,25 @@ vi: ...@@ -149,8 +151,25 @@ vi:
user_id: '' user_id: ''
favorite: favorite:
user_id: '' user_id: ''
admin:
search: 'Tìm kiếm'
dl: 'Tải về CSV'
show_all: 'Hiển thị tất cả'
filter: 'Lọc'
no_record: 'Không kết quả phù hợp'
has_record: ' %{result_count} kết quả'
profile:
title: 'Thông tin thí sinh'
name: 'Họ tên: '
email: 'Email: '
join_at: 'Ngày tham gia: '
header_csv:
job_id: 'Tên công việc'
name: 'Tên thí sinh'
email: 'Email'
cv: 'Đường dẫn tệp cv'
created_at: 'Ứng tuyển vào'
views: views:
pagination: pagination:
last: 'Cuối' last: 'Cuối'
first: 'Đầu' first: 'Đầu'
\ No newline at end of file
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
Rails.application.routes.draw do Rails.application.routes.draw do
get 'setting', to: 'users#set_lang', as: :set_lang get 'setting', to: 'users#set_lang', as: :set_lang
scope '(:locale)', locale: /en|vi/ do scope '(:locale)', locale: /en|vi/ do
devise_for :users, controllers: { registrations: 'registrations' }
devise_for :admins, path: 'admin', path_names: { sign_in: 'login', sign_out: 'logout'}
root 'home#index'
get 'admin/search', to: 'admin/admin#search', as: :applies
get 'admin/applies', to: 'admin/admin#index', as: :applies_index
get 'admin', to: 'admin/admin#routing', as: :admin
get 'info/user/:user_id', to: 'users#personal_page', as: :personal_page
devise_for :users, controllers: { registrations: 'registrations', passwords: 'passwords'} devise_for :users, controllers: { registrations: 'registrations', passwords: 'passwords'}
root 'home#index' root 'home#index'
# Search # Search
......
# frozen_string_literal: true
class DeviseCreateAdmins < ActiveRecord::Migration[5.2]
def change
create_table :admins 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 :admins, :email, unique: true
add_index :admins, :reset_password_token, unique: true
# add_index :admins, :confirmation_token, unique: true
# add_index :admins, :unlock_token, unique: true
end
end
...@@ -10,7 +10,27 @@ ...@@ -10,7 +10,27 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_08_17_004611) do ActiveRecord::Schema.define(version: 2020_09_07_010650) do
create_table "admins", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade 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.integer "failed_attempts", default: 0, null: false
t.string "unlock_token"
t.datetime "locked_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["email"], name: "index_admins_on_email", unique: true
t.index ["reset_password_token"], name: "index_admins_on_reset_password_token", unique: true
end
create_table "applied_jobs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| create_table "applied_jobs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.bigint "user_id" t.bigint "user_id"
......
# frozen_string_literal: true
require 'csv'
# Export file csv
class ExportCsv
def initialize(objects, attributes)
@attributes = attributes
@objects = objects
@header = attributes.map { |attr| I18n.t("header_csv.#{attr}") }
end
def perform
CSV.generate do |csv|
csv << header if csv.tell.zero?
objects.includes(:job).each do |obj|
csv << convert_data(obj)
end
end
end
private
def convert_data(obj)
data = []
data << obj.job.name
data << obj.name
data << obj.email
data << obj.cv
data << obj.created_at.localtime
data
end
attr_reader :attributes, :objects, :header
end
# frozen_string_literal: true
namespace :admin do
task create_acc: :environment do
Admin.create do |ad|
ad.email = 'admin@mi.com'
ad.password = '11111111'
ad.password_confirmation = '11111111'
end
end
task dumb_data: :environment do
logger = Logger.new(Rails.root.join('log', 'dumb_data.log'))
user = User.find 1
3000.times do |i|
user.applied_jobs.create! do |obj|
obj.user_id = user.id
obj.job_id = i
obj.name = user.name
obj.email = user.email
obj.cv = user.cv
end
rescue StandardError => e
logger.error e
end
end
end
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
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