Browse Source

Implement date filters

master
Dylan Baker 3 years ago
parent
commit
b3aafafa29
5 changed files with 189 additions and 93 deletions
  1. 45
    10
      lib/search.rb
  2. 11
    1
      web/assets/styles/form.scss
  3. 18
    6
      web/server.rb
  4. 52
    22
      web/views/partials/search.erb
  5. 63
    54
      web/views/results.erb

+ 45
- 10
lib/search.rb View File

@@ -4,7 +4,38 @@ def search(params)
4 4
   query = params[:q].strip
5 5
   offset = (params[:page] - 1) * 10
6 6
   username = params[:username].strip
7
-  case params[:type]
7
+  from_date = params[:from_date].strip
8
+  to_date = params[:to_date].strip
9
+
10
+  errors = Array.new
11
+
12
+  if from_date.empty?
13
+    from_date = nil
14
+  else
15
+    if from_date.match(/\d{4}-\d{2}-\d{2}/)
16
+      from_date = Date.parse(params[:from_date]) rescue errors << 'Invalid From Date'
17
+    else
18
+      errors << 'From Date must be in the format YYYY-MM-DD'
19
+    end
20
+  end
21
+
22
+  if to_date.empty?
23
+    to_date = nil
24
+  else
25
+    if to_date.match(/\d{4}-\d{2}-\d{2}/)
26
+      to_date = Date.parse(params[:to_date]).next rescue errors << 'Invalid To Date'
27
+    else
28
+      errors << 'To Date must be in the format YYYY-MM-DD'
29
+    end
30
+  end
31
+
32
+  if errors.empty? && !to_date.nil? && !from_date.nil? &&  to_date < from_date
33
+    errors << 'To Date must be after From Date'
34
+  end
35
+
36
+  return {results: Array.new, errors: errors} unless errors.empty?
37
+
38
+  results = case params[:type]
8 39
   when 'threads'
9 40
     sort =
10 41
       case params[:sort]
@@ -15,30 +46,34 @@ def search(params)
15 46
       else
16 47
         'created_at DESC'
17 48
       end
18
-    search_threads(query, username, sort, offset)
49
+    search_threads(query, username, from_date, to_date, sort, offset)
19 50
   when 'posts'
20
-    search_posts(query, username, offset)
51
+    search_posts(query, username, from_date, to_date, offset)
21 52
   else
22 53
     Array.new
23 54
   end
55
+
56
+  {results: results, errors: errors}
24 57
 end
25 58
 
26
-def search_threads(query, username, sort, offset)
27
-  DB[<<-SQL, query, username, username, offset]
59
+def search_threads(query, username, from_date, to_date, sort, offset)
60
+  DB[<<-SQL, query, username, username, from_date, from_date, to_date, to_date, offset]
28 61
     SELECT
29 62
       threads.*
30 63
     FROM threads
31 64
     WHERE
32 65
       to_tsvector(title) @@ plainto_tsquery(?)
33 66
       AND (LOWER(threads.creator) = LOWER(?) OR ? = '')
67
+      AND (created_at >= ? OR ? IS NULL)
68
+      AND (created_at <= ? OR ? IS NULL)
34 69
     ORDER BY #{sort}
35 70
     LIMIT 50
36 71
     OFFSET ?;
37 72
   SQL
38 73
 end
39 74
 
40
-def search_posts(query, username, offset)
41
-  DB[<<-SQL, query, username, username, offset]
75
+def search_posts(query, username, from_date, to_date, offset)
76
+  DB[<<-SQL, query, username, username, from_date, from_date, to_date, to_date, offset]
42 77
     SELECT
43 78
       posts.*,
44 79
       threads.title as thread_title,
@@ -47,9 +82,9 @@ def search_posts(query, username, offset)
47 82
     INNER JOIN threads on posts.thread_id = threads.id
48 83
     WHERE
49 84
       tsv @@ plainto_tsquery(?)
50
-      AND (
51
-        (LOWER(posts.creator) = LOWER(?)) OR (? = '')
52
-      )
85
+      AND ((LOWER(posts.creator) = LOWER(?)) OR (? = ''))
86
+      AND (posts.created_at >= ? OR ? IS NULL)
87
+      AND (posts.created_at <= ? OR ? IS NULL)
53 88
     ORDER BY created_at DESC
54 89
     LIMIT 50
55 90
     OFFSET ?;

+ 11
- 1
web/assets/styles/form.scss View File

@@ -17,12 +17,22 @@
17 17
   margin: 1em 0;
18 18
 }
19 19
 
20
+.filters__section {
21
+  display: flex;
22
+  padding: .5em 0;
23
+}
24
+
20 25
 .filters__section--sort {
21 26
   display: none;
22 27
 }
23 28
 
24 29
 .filters__section--sort.open {
25
-  display: block;
30
+  display: flex;
31
+}
32
+
33
+.filters__subsection {
34
+  flex: 1;
35
+  padding: 0 1em;
26 36
 }
27 37
 
28 38
 .form__field {

+ 18
- 6
web/server.rb View File

@@ -34,16 +34,26 @@ class VLVSearch < Sinatra::Base
34 34
     params[:page] = params[:page].to_i
35 35
     params[:q] = String.new unless params[:q]
36 36
     params[:username] = String.new unless params[:username]
37
+    params[:from_date] = String.new unless params[:from_date]
38
+    params[:to_date] = String.new unless params[:to_date]
37 39
 
38 40
     results = search(params)
39
-    previous_url, next_url = build_urls(params)
40 41
 
41
-    locals =
42
-      params.merge(
43
-        results: results, previous_url: previous_url, next_url: next_url
44
-      )
42
+    unless results[:errors].empty?
43
+      erb :results, { locals: {errors: results[:errors]}, layout: :layout }
44
+    else
45
+      previous_url, next_url = build_urls(params)
46
+
47
+      locals =
48
+        params.merge(
49
+          results: results[:results],
50
+          previous_url: previous_url,
51
+          next_url: next_url,
52
+          errors: Array.new,
53
+        )
45 54
 
46
-    erb :results, { locals: locals, layout: :layout }
55
+      erb :results, { locals: locals, layout: :layout }
56
+    end
47 57
   end
48 58
 
49 59
   get '/login' do
@@ -79,6 +89,8 @@ class VLVSearch < Sinatra::Base
79 89
 
80 90
       url_params = { q: params[:q], type: params[:type] }
81 91
       url_params[:username] = params[:username] if params[:username]
92
+      url_params[:from_date] = params[:from_date] if params[:from_date]
93
+      url_params[:to_date] = params[:to_date] if params[:to_date]
82 94
 
83 95
       [previous_page, next_page].map do |page|
84 96
         URI::Generic.build(

+ 52
- 22
web/views/partials/search.erb View File

@@ -2,30 +2,60 @@
2 2
   <input name="q" type="search" value="<%= params[:q] %>" placeholder="Search for..." class="form__search" required>
3 3
   <div class="filters">
4 4
     <div class="filters__section">
5
-      <p>Search in:</p>
6
-      <label class="form__label">
7
-        <input type="radio" name="type" value="threads" <% if [nil, "threads"].include?(params[:type]) %>checked<% end%>>
8
-        Threads
9
-      </label>
10
-      <label class="form__label">
11
-        <input type="radio" name="type" value="posts" <% if params[:type] == "posts" %>checked<% end %>>
12
-        Posts
13
-      </label>
5
+      <div class="filters__subsection">
6
+        <p>Search in:</p>
7
+        <label class="form__label">
8
+          <input type="radio" name="type" value="threads" <% if [nil, "threads"].include?(params[:type]) %>checked<% end%>>
9
+          Threads
10
+        </label>
11
+        <label class="form__label">
12
+          <input type="radio" name="type" value="posts" <% if params[:type] == "posts" %>checked<% end %>>
13
+          Posts
14
+        </label>
15
+      </div>
16
+      <div class="filters__subsection">
17
+        <p>From Date <em>(YYYY-MM-DD)</em>:</p>
18
+        <label class="form__label">
19
+          <input
20
+          type="text"
21
+          name="from_date"
22
+          value="<%= params[:from_date] %>"
23
+          class="form__text-field"
24
+          pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"
25
+          maxlength="10"
26
+        >
27
+        </label>
28
+      </div>
29
+      <div class="filters__subsection">
30
+        <p>To Date <em>(YYYY-MM-DD)</em>:</p>
31
+        <label class="form__label">
32
+          <input
33
+          type="text"
34
+          name="to_date"
35
+          value="<%= params[:to_date] %>"
36
+          class="form__text-field"
37
+          pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"
38
+          maxlength="10"
39
+        >
40
+        </label>
41
+      </div>
14 42
     </div>
15 43
     <div class="filters__section filters__section--sort <%= params[:type] == 'threads' ? 'open' : '' %>">
16
-      <p>Sort by:</p>
17
-      <label class="form__label">
18
-        <input type="radio" name="sort" value="thread" <% if [nil, "thread"].include? params[:sort] %>checked<% end%>>
19
-        Thread creation
20
-      </label>
21
-      <label class="form__label">
22
-        <input type="radio" name="sort" value="post" <% if params[:sort] == "post" %>checked<% end %>>
23
-        Most recent post
24
-      </label>
25
-    </div>
26
-    <div class="filters__section">
27
-      <p>Posted by:</p>
28
-      <input type="text" name="username" value="<%= params[:username] %>" class="form__text-field">
44
+      <div class="filters__subsection">
45
+        <p>Sort by:</p>
46
+        <label class="form__label">
47
+          <input type="radio" name="sort" value="thread" <% if [nil, "thread"].include? params[:sort] %>checked<% end%>>
48
+          Thread creation
49
+        </label>
50
+        <label class="form__label">
51
+          <input type="radio" name="sort" value="post" <% if params[:sort] == "post" %>checked<% end %>>
52
+          Most recent post
53
+        </label>
54
+      </div>
55
+      <div class="filters__subsection">
56
+        <p>Posted by:</p>
57
+        <input type="text" name="username" value="<%= params[:username] %>" class="form__text-field">
58
+      </div>
29 59
     </div>
30 60
   </div>
31 61
   <input type="submit" value="Search" class="btn form__submit">

+ 63
- 54
web/views/results.erb View File

@@ -1,63 +1,72 @@
1 1
 <%= erb :'partials/search' %>
2 2
 
3 3
 <div class="results-container">
4
-  <% if params[:q] %>
5
-    <p>Showing results for <strong><em><%= params[:q] %></em></strong>:</p>
6
-  <% end %>
7
-  <div class="results">
8
-    <% if results.empty? %>
9
-      <h3>No results!</h3>
4
+  <% if errors.empty? %>
5
+    <% if params[:q] %>
6
+      <p>Showing results for <strong><em><%= params[:q] %></em></strong>:</p>
10 7
     <% end %>
11
-    <% results.each do |result| %>
12
-      <div class="results__result <%= params[:type] %>">
13
-        <% if params[:type] == "threads" %>
14
-          <%= external_link(
15
-            "http://board.vivalavinyl.com/thread/view/#{result[:remote_id]}",
16
-            result[:title]
17
-          ) %>
18
-          <p class="result__info">
19
-            <span>
20
-              created by <%= result[:creator] %>
21
-              on <%= result[:created_at].strftime('%B %d, %Y') %>
22
-            </span>
23
-            <span>
24
-              last post by <%= result[:last_post_creator] %>
25
-              at <%= result[:last_post_created_at].strftime('%-I:%M %p EST') %>
26
-              on <%= result[:last_post_created_at].strftime('%B %-d, %Y') %>
27
-            </span>
28
-          </p>
29
-        <% elsif params[:type] == "posts" %>
30
-          <p>
31
-            In thread:
32
-            <strong>
33
-              <%= external_link(
34
-                "http://board.vivalavinyl.com/thread/view/#{result[:remote_thread_id]}",
35
-                result[:thread_title]
36
-              ) %>
37
-            </strong>
38
-          </p>
39
-          <p class="result__info">
40
-            <%= result[:creator] %> posted this at <%= result[:created_at] %>
41
-          </p>
42
-          <p class="result__body">
43
-            <%= result[:body] %>
44
-          </p>
8
+    <div class="results">
9
+      <% if results.empty? %>
10
+        <h3>No results!</h3>
11
+      <% end %>
12
+      <% results.each do |result| %>
13
+        <div class="results__result <%= params[:type] %>">
14
+          <% if params[:type] == "threads" %>
15
+            <%= external_link(
16
+              "http://board.vivalavinyl.com/thread/view/#{result[:remote_id]}",
17
+              result[:title]
18
+            ) %>
19
+            <p class="result__info">
20
+              <span>
21
+                created by <%= result[:creator] %>
22
+                on <%= result[:created_at].strftime('%B %d, %Y') %>
23
+              </span>
24
+              <span>
25
+                last post by <%= result[:last_post_creator] %>
26
+                at <%= result[:last_post_created_at].strftime('%-I:%M %p EST') %>
27
+                on <%= result[:last_post_created_at].strftime('%B %-d, %Y') %>
28
+              </span>
29
+            </p>
30
+          <% elsif params[:type] == "posts" %>
31
+            <p>
32
+              In thread:
33
+              <strong>
34
+                <%= external_link(
35
+                  "http://board.vivalavinyl.com/thread/view/#{result[:remote_thread_id]}",
36
+                  result[:thread_title]
37
+                ) %>
38
+              </strong>
39
+            </p>
40
+            <p class="result__info">
41
+              <%= result[:creator] %> posted this at <%= result[:created_at] %>
42
+            </p>
43
+            <p class="result__body">
44
+              <%= result[:body] %>
45
+            </p>
46
+          <% end %>
47
+        </div>
48
+      <% end %>
49
+
50
+      <% if params[:q] %>
51
+        <% if params[:page] > 1 %>
52
+          <a class="btn btn--small btn--prev" href="<%= previous_url %>">
53
+            previous page
54
+          </a>
45 55
         <% end %>
46
-      </div>
47
-    <% end %>
48 56
 
49
-    <% if params[:q] %>
50
-      <% if params[:page] > 1 %>
51
-        <a class="btn btn--small btn--prev" href="<%= previous_url %>">
52
-          previous page
53
-        </a>
57
+        <% unless results.empty? %>
58
+          <a class="btn btn--small btn--next" href="<%= next_url %>">
59
+            next page
60
+          </a>
61
+        <% end %>
54 62
       <% end %>
55
-
56
-      <% unless results.empty? %>
57
-        <a class="btn btn--small btn--next" href="<%= next_url %>">
58
-          next page
59
-        </a>
63
+    </div>
64
+  <% else %>
65
+    <div class="errors">
66
+      <h3 class="errors__heading">Error(s):</h3>
67
+      <% errors.each do |error| %>
68
+        <p class="errors__error error"><%= error %></p>
60 69
       <% end %>
61
-    <% end %>
62
-  </div>
70
+    </div>
71
+  <% end %>
63 72
 </div>

Loading…
Cancel
Save