Skip to content

Commit fcf8440

Browse files
committed
fix ci issues
1 parent 713cb61 commit fcf8440

File tree

13 files changed

+140
-98
lines changed

13 files changed

+140
-98
lines changed

.rubocop.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,12 +1890,14 @@ Rails/FindById: # new in 2.7
18901890
Enabled: true
18911891
Rails/FreezeTime: # new in 2.16
18921892
Enabled: true
1893+
Rails/HelperInstanceVariable:
1894+
Enabled: false
18931895
Rails/I18nLazyLookup: # new in 2.14
18941896
Enabled: true
18951897
Rails/I18nLocaleAssignment: # new in 2.11
18961898
Enabled: true
18971899
Rails/I18nLocaleTexts: # new in 2.14
1898-
Enabled: true
1900+
Enabled: false
18991901
Rails/IgnoredColumnsAssignment: # new in 2.17
19001902
Enabled: true
19011903
Rails/Inquiry: # new in 2.7
@@ -1979,4 +1981,4 @@ FactoryBot/IdSequence: # new in 2.24
19791981
FactoryBot/RedundantFactoryOption: # new in 2.23
19801982
Enabled: true
19811983
FactoryBot/SyntaxMethods: # new in 2.7
1982-
Enabled: true
1984+
Enabled: true

Gemfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ gem "tzinfo-data", "~> 1.2024", ">= 1.2024.1", platforms: %i[windows jruby]
1414
gem "vite_rails", "~> 3.0", ">= 3.0.17"
1515
gem "phlex-rails", "~> 1.2"
1616
gem "devise", "~> 4.9"
17-
gem 'will_paginate', '~> 4.0'
17+
gem "will_paginate", "~> 4.0"
18+
gem "validate_url", "~> 1.0"
1819

1920
group :development, :test do
2021
gem "debug", "~> 1.9", ">= 1.9.2", platforms: %i[mri windows]

Gemfile.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ GEM
315315
tzinfo (2.0.6)
316316
concurrent-ruby (~> 1.0)
317317
unicode-display_width (2.5.0)
318+
validate_url (1.0.15)
319+
activemodel (>= 3.0.0)
320+
public_suffix
318321
vite_rails (3.0.17)
319322
railties (>= 5.1, < 8)
320323
vite_ruby (~> 3.0, >= 3.2.2)
@@ -373,6 +376,7 @@ DEPENDENCIES
373376
stimulus-rails (~> 1.3, >= 1.3.3)
374377
turbo-rails (~> 2.0, >= 2.0.5)
375378
tzinfo-data (~> 1.2024, >= 1.2024.1)
379+
validate_url (~> 1.0)
376380
vite_rails (~> 3.0, >= 3.0.17)
377381
web-console (~> 4.2, >= 4.2.1)
378382
will_paginate (~> 4.0)

app/controllers/job_applications_controller.rb

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,18 @@ class JobApplicationsController < ApplicationController
22
before_action :set_job_application, only: [:create, :update, :destroy]
33

44
def index
5-
@job_applications = JobApplication.all
6-
7-
if params[:search].present?
8-
@job_applications = @job_applications.where("company_name ILIKE ? OR position_title ILIKE ?", "%#{params[:search]}%", "%#{params[:search]}%")
9-
end
10-
11-
if params[:method_of_contact].present?
12-
@job_applications = @job_applications.where(method_of_contact: params[:method_of_contact])
13-
end
14-
15-
if params[:position_type].present?
16-
@job_applications = @job_applications.where(position_type: params[:position_type])
17-
end
18-
5+
@job_applications = filter_and_sort_job_applications
196
@job_application_count = @job_applications.count
20-
21-
@job_applications = if params[:sort].present? && params[:direction].present?
22-
@job_applications.order(params[:sort] => params[:direction])
23-
else
24-
@job_applications.order(date_applied: :desc)
25-
end
26-
277
@job_applications = @job_applications.paginate(page: params[:page], per_page: 10)
288

9+
@pagination_info = {
10+
current_page: @job_applications.current_page,
11+
total_pages: @job_applications.total_pages,
12+
offset: @job_applications.offset,
13+
length: @job_applications.length,
14+
total_entries: @job_applications.total_entries
15+
}
16+
2917
respond_to do |format|
3018
format.html
3119
format.turbo_stream
@@ -99,4 +87,24 @@ def set_job_application
9987
def job_application_params
10088
params.require(:job_application).permit(:date_applied, :company_name, :method_of_contact, :email_address, :point_of_contact, :website_link, :position_type, :position_title)
10189
end
90+
91+
def filter_and_sort_job_applications
92+
job_applications = JobApplication.all
93+
94+
job_applications = job_applications.search(params[:search]) if params[:search].present?
95+
job_applications = job_applications.by_method_of_contact(params[:method_of_contact]) if params[:method_of_contact].present?
96+
job_applications = job_applications.by_position_type(params[:position_type]) if params[:position_type].present?
97+
98+
sort_column = sort_column(params[:sort])
99+
sort_direction = sort_direction(params[:direction])
100+
job_applications.order(sort_column => sort_direction)
101+
end
102+
103+
def sort_column(column)
104+
%w[date_applied company_name position_title].include?(column) ? column : "date_applied"
105+
end
106+
107+
def sort_direction(direction)
108+
%w[asc desc].include?(direction) ? direction : "desc"
109+
end
102110
end

app/helpers/application_helper.rb

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,24 @@ def flash_class(type)
1010
end
1111

1212
def sort_link_to(name, column)
13-
direction = (column.to_s == params[:sort] && params[:direction] == 'asc') ? 'desc' : 'asc'
14-
link_to name, { sort: column, direction: direction },
15-
class: 'text-gray-600 hover:text-gray-900',
16-
data: {
17-
turbo_frame: 'job_applications_table',
18-
turbo_action: 'replace'
19-
}
13+
direction = (column.to_s == params[:sort] && params[:direction] == "asc") ? "desc" : "asc"
14+
link_to name,
15+
request.params.merge(sort: column, direction: direction),
16+
class: "text-gray-600 hover:text-gray-900",
17+
data: {
18+
turbo_frame: "job_applications_table",
19+
turbo_action: "replace"
20+
}
21+
end
22+
23+
def safe_url(url)
24+
uri = URI.parse(url)
25+
if uri.scheme && !["http", "https"].include?(uri.scheme)
26+
"#" # or some default safe URL
27+
else
28+
url
29+
end
30+
rescue URI::InvalidURIError
31+
"#" # or some default safe URL
2032
end
2133
end

app/helpers/custom_pagination_renderer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ def pagination
1717

1818
def previous_page
1919
num = @collection.current_page > 1 && @collection.current_page - 1
20-
previous_or_next_page(num, @options[:previous_label], 'previous_page')
20+
previous_or_next_page(num, @options[:previous_label], "previous_page")
2121
end
2222

2323
def next_page
2424
num = @collection.current_page < total_pages && @collection.current_page + 1
25-
previous_or_next_page(num, @options[:next_label], 'next_page')
25+
previous_or_next_page(num, @options[:next_label], "next_page")
2626
end
2727

2828
def previous_or_next_page(page, text, classname)

app/models/job_application.rb

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
class JobApplication < ApplicationRecord
22
validates :date_applied, :company_name, :method_of_contact, :position_type, :position_title, presence: true
3-
validates :email_address, presence: true, if: -> { method_of_contact == 'email' }
4-
validates :point_of_contact, presence: true, if: -> { ['email', 'phone', 'recruiter', 'other'].include?(method_of_contact) }
5-
validates :website_link, presence: true, if: -> { method_of_contact == 'internet job application' }
3+
validates :email_address, presence: true, if: -> { method_of_contact == "email" }
4+
validates :point_of_contact, presence: true, if: -> { ["email", "phone", "recruiter", "other"].include?(method_of_contact) }
5+
validates :website_link, presence: true, if: -> { method_of_contact == "internet job application" }
6+
validates :website_link, url: {
7+
allow_blank: true,
8+
schemes: ["http", "https"],
9+
no_local: true,
10+
public_suffix: true
11+
}
12+
enum method_of_contact: {email: "email", phone: "phone", internet_job_application: "internet job application", recruiter: "recruiter", other: "other"}
13+
enum position_type: {full_time: "full-time", part_time: "part-time", internship: "internship"}
614

7-
enum method_of_contact: { email: 'email', phone: 'phone', internet_job_application: 'internet job application', recruiter: 'recruiter', other: 'other' }
8-
enum position_type: { full_time: 'full-time', part_time: 'part-time', internship: 'internship' }
15+
scope :search, ->(query) { where("company_name ILIKE ? OR position_title ILIKE ?", "%#{query}%", "%#{query}%") }
16+
scope :by_method_of_contact, ->(method) { where(method_of_contact: method) }
17+
scope :by_position_type, ->(type) { where(position_type: type) }
918
end

app/views/job_applications/_job_application.html.erb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@
2222
</td>
2323
<td class="px-5 py-5 border-b border-gray-200 bg-white text-sm">
2424
<% if job_application.website_link.present? %>
25-
<%= link_to 'Visit', job_application.website_link, target: "_blank", class: "px-3 py-1 rounded-md text-sm font-medium text-gray-700 bg-white border border-gray-300 hover:bg-gray-50", title: "Visit Website" %>
25+
<%= link_to 'Visit',
26+
safe_url(job_application.website_link),
27+
target: "_blank",
28+
rel: "noopener noreferrer",
29+
class: "px-3 py-1 rounded-md text-sm font-medium text-gray-700 bg-white border border-gray-300 hover:bg-gray-50",
30+
title: "Visit Website" %>
2631
<% end %>
2732
</td>
2833
<td class="px-5 py-5 border-b border-gray-200 bg-white text-sm">

app/views/job_applications/_job_applications_table.html.erb

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,49 @@
44
<table class="min-w-full leading-normal">
55
<thead>
66
<tr>
7-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
8-
<%= sort_link_to 'Applied', :date_applied %>
9-
</th>
10-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
11-
<%= sort_link_to 'Company', :company_name %>
12-
</th>
13-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
14-
<%= sort_link_to 'Position', :position_title %>
15-
</th>
16-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
17-
Type
18-
</th>
19-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
20-
Contact Method
21-
</th>
22-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
23-
P.o.C.
24-
</th>
25-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
26-
Email
27-
</th>
28-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
29-
Website
30-
</th>
31-
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
32-
Actions
33-
</th>
34-
</tr>
35-
</thead>
36-
<tbody id="job_applications">
37-
<%= render @job_applications %>
38-
</tbody>
39-
</table>
40-
<% else %>
41-
<div class="text-center py-10">
42-
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
43-
<path vector-effect="non-scaling-stroke" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
44-
</svg>
45-
<p class="mt-1 text-sm text-gray-500">
46-
<%= "No results match your search criteria." if params[:search].present? || params[:method_of_contact].present? || params[:position_type].present? %>
47-
</p>
48-
</div>
49-
<% end %>
50-
</div>
51-
<% end %>
7+
<tr>
8+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
9+
<%= sort_link_to 'Applied', 'date_applied' %>
10+
</th>
11+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
12+
<%= sort_link_to 'Company', 'company_name' %>
13+
</th>
14+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
15+
<%= sort_link_to 'Position', 'position_title' %>
16+
</th>
17+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
18+
Type
19+
</th>
20+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
21+
Contact Method
22+
</th>
23+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
24+
P.o.C.
25+
</th>
26+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
27+
Email
28+
</th>
29+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
30+
Website
31+
</th>
32+
<th class="px-5 py-3 border-b-2 border-gray-200 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider">
33+
Actions
34+
</th>
35+
</tr>
36+
</thead>
37+
<tbody id="job_applications">
38+
<%= render partial: 'job_application', collection: job_applications %>
39+
</tbody>
40+
</table>
41+
<% else %>
42+
<div class="text-center py-10">
43+
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
44+
<path vector-effect="non-scaling-stroke" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
45+
</svg>
46+
<p class="mt-1 text-sm text-gray-500">
47+
<%= "No results match your search criteria." if params[:search].present? || params[:method_of_contact].present? || params[:position_type].present? %>
48+
</p>
49+
</div>
50+
<% end %>
51+
</div>
52+
<% end %>
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
<% if @job_applications.total_pages > 1 %>
1+
<% if @pagination_info[:total_pages] > 1 %>
22
<div class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6 shadow appearance-none border rounded w-full text-gray-700 leading-tight focus:outline-none focus:shadow-outline">
33
<div class="text-sm text-gray-700">
4-
Showing <span class="font-medium"><%= @job_applications.offset + 1 %></span> to <span class="font-medium"><%= [@job_applications.offset + @job_applications.length, @job_application_count].min %></span> of <span class="font-medium"><%= @job_application_count %></span> results
4+
Showing <span class="font-medium"><%= @pagination_info[:offset] + 1 %></span> to <span class="font-medium"><%= [@pagination_info[:offset] + @pagination_info[:length], @job_application_count].min %></span> of <span class="font-medium"><%= @job_application_count %></span> results
55
</div>
66
<div>
77
<%= will_paginate @job_applications,
8-
renderer: CustomPaginationRenderer,
9-
previous_label: 'Previous',
10-
next_label: 'Next',
11-
inner_window: 0,
12-
outer_window: 0,
13-
class: 'pagination',
14-
previous_page_class: 'px-3 py-1 rounded-md text-sm font-medium text-gray-700 bg-white border border-gray-300 hover:bg-gray-50',
15-
next_page_class: 'px-3 py-1 rounded-md text-sm font-medium text-gray-700 bg-white border border-gray-300 hover:bg-gray-50' %>
8+
renderer: CustomPaginationRenderer,
9+
previous_label: 'Previous',
10+
next_label: 'Next',
11+
inner_window: 0,
12+
outer_window: 0,
13+
class: 'pagination',
14+
previous_page_class: 'px-3 py-1 rounded-md text-sm font-medium text-gray-700 bg-white border border-gray-300 hover:bg-gray-50',
15+
next_page_class: 'px-3 py-1 rounded-md text-sm font-medium text-gray-700 bg-white border border-gray-300 hover:bg-gray-50' %>
1616
</div>
1717
</div>
1818
<% end %>

0 commit comments

Comments
 (0)