6 次程式碼提交

作者 SHA1 備註 提交日期
  Dylan Baker e5bc0c6a43 Fix slow query 8 月之前
  Dylan Baker d54a3e8beb Add host and port to DB connection config 8 月之前
  Dylan Baker ed1c79d762 Fix padding differences between different sizes of results 8 月之前
  Dylan Baker ea74015ef8 Upgrade ruby, switch to puma 8 月之前
  Dylan Baker 1fd64ecb2e Fix for updated vlv header 8 月之前
  Dylan Baker 3ed08aeb76 Ditch scss 8 月之前

+ 1
- 1
.ruby-version 查看文件

@@ -1 +1 @@
1
-2.6.3@vlv-search
1
+3.3.4

+ 2
- 1
Gemfile 查看文件

@@ -10,9 +10,10 @@ gem 'pg', '~> 1.2'
10 10
 gem 'rack', '~> 2.2'
11 11
 gem 'rake', '~> 13.0'
12 12
 gem 'rspec', '~> 3.9'
13
-gem 'sassc', '~> 2.2'
14 13
 gem 'sequel', '~> 5.30'
15 14
 gem 'sinatra', '~> 2.0'
16 15
 gem "truncato", "~> 0.7.11"
17 16
 gem "vcr", "~> 6.0"
18 17
 gem "webmock", "~> 3.14"
18
+
19
+gem "puma", "~> 6.4"

+ 70
- 47
Gemfile.lock 查看文件

@@ -1,78 +1,101 @@
1 1
 GEM
2 2
   remote: https://rubygems.org/
3 3
   specs:
4
-    addressable (2.8.0)
5
-      public_suffix (>= 2.0.2, < 5.0)
6
-    crack (0.4.5)
4
+    addressable (2.8.7)
5
+      public_suffix (>= 2.0.2, < 7.0)
6
+    base64 (0.2.0)
7
+    bigdecimal (3.1.8)
8
+    crack (1.0.0)
9
+      bigdecimal
7 10
       rexml
8
-    diff-lcs (1.3)
9
-    dotenv (2.7.5)
10
-    ffi (1.12.2)
11
-    hashdiff (1.0.1)
11
+    diff-lcs (1.5.1)
12
+    dotenv (2.8.1)
13
+    hashdiff (1.1.1)
12 14
     htmlentities (4.3.4)
13
-    httparty (0.18.0)
15
+    httparty (0.18.1)
14 16
       mime-types (~> 3.0)
15 17
       multi_xml (>= 0.5.2)
16
-    mime-types (3.3.1)
18
+    mime-types (3.5.2)
17 19
       mime-types-data (~> 3.2015)
18
-    mime-types-data (3.2019.1009)
19
-    mini_portile2 (2.4.0)
20
-    multi_xml (0.6.0)
21
-    mustermann (1.1.1)
20
+    mime-types-data (3.2024.0820)
21
+    multi_xml (0.7.1)
22
+      bigdecimal (~> 3.1)
23
+    mustermann (2.0.2)
22 24
       ruby2_keywords (~> 0.0.1)
23
-    nokogiri (1.10.9)
24
-      mini_portile2 (~> 2.4.0)
25
-    pg (1.2.3)
26
-    public_suffix (4.0.6)
27
-    rack (2.2.2)
28
-    rack-protection (2.0.8.1)
25
+    nio4r (2.7.3)
26
+    nokogiri (1.16.7-aarch64-linux)
27
+      racc (~> 1.4)
28
+    nokogiri (1.16.7-arm-linux)
29
+      racc (~> 1.4)
30
+    nokogiri (1.16.7-arm64-darwin)
31
+      racc (~> 1.4)
32
+    nokogiri (1.16.7-x86-linux)
33
+      racc (~> 1.4)
34
+    nokogiri (1.16.7-x86_64-darwin)
35
+      racc (~> 1.4)
36
+    nokogiri (1.16.7-x86_64-linux)
37
+      racc (~> 1.4)
38
+    pg (1.5.7)
39
+    public_suffix (6.0.1)
40
+    puma (6.4.2)
41
+      nio4r (~> 2.0)
42
+    racc (1.8.1)
43
+    rack (2.2.9)
44
+    rack-protection (2.2.4)
29 45
       rack
30
-    rake (13.0.1)
31
-    rexml (3.2.5)
32
-    rspec (3.9.0)
33
-      rspec-core (~> 3.9.0)
34
-      rspec-expectations (~> 3.9.0)
35
-      rspec-mocks (~> 3.9.0)
36
-    rspec-core (3.9.1)
37
-      rspec-support (~> 3.9.1)
38
-    rspec-expectations (3.9.1)
46
+    rake (13.2.1)
47
+    rexml (3.3.5)
48
+      strscan
49
+    rspec (3.13.0)
50
+      rspec-core (~> 3.13.0)
51
+      rspec-expectations (~> 3.13.0)
52
+      rspec-mocks (~> 3.13.0)
53
+    rspec-core (3.13.0)
54
+      rspec-support (~> 3.13.0)
55
+    rspec-expectations (3.13.2)
39 56
       diff-lcs (>= 1.2.0, < 2.0)
40
-      rspec-support (~> 3.9.0)
41
-    rspec-mocks (3.9.1)
57
+      rspec-support (~> 3.13.0)
58
+    rspec-mocks (3.13.1)
42 59
       diff-lcs (>= 1.2.0, < 2.0)
43
-      rspec-support (~> 3.9.0)
44
-    rspec-support (3.9.2)
45
-    ruby2_keywords (0.0.2)
46
-    sassc (2.2.1)
47
-      ffi (~> 1.9)
48
-    sequel (5.31.0)
49
-    sinatra (2.0.8.1)
50
-      mustermann (~> 1.0)
51
-      rack (~> 2.0)
52
-      rack-protection (= 2.0.8.1)
60
+      rspec-support (~> 3.13.0)
61
+    rspec-support (3.13.1)
62
+    ruby2_keywords (0.0.5)
63
+    sequel (5.83.1)
64
+      bigdecimal
65
+    sinatra (2.2.4)
66
+      mustermann (~> 2.0)
67
+      rack (~> 2.2)
68
+      rack-protection (= 2.2.4)
53 69
       tilt (~> 2.0)
54
-    tilt (2.0.10)
55
-    truncato (0.7.11)
70
+    strscan (3.1.0)
71
+    tilt (2.4.0)
72
+    truncato (0.7.12)
56 73
       htmlentities (~> 4.3.1)
57 74
       nokogiri (>= 1.7.0, <= 2.0)
58
-    vcr (6.0.0)
59
-    webmock (3.14.0)
75
+    vcr (6.3.1)
76
+      base64
77
+    webmock (3.23.1)
60 78
       addressable (>= 2.8.0)
61 79
       crack (>= 0.3.2)
62 80
       hashdiff (>= 0.4.0, < 2.0.0)
63 81
 
64 82
 PLATFORMS
65
-  ruby
83
+  aarch64-linux
84
+  arm-linux
85
+  arm64-darwin
86
+  x86-linux
87
+  x86_64-darwin
88
+  x86_64-linux
66 89
 
67 90
 DEPENDENCIES
68 91
   dotenv (~> 2.7)
69 92
   httparty (~> 0.18.0)
70 93
   nokogiri (~> 1.10)
71 94
   pg (~> 1.2)
95
+  puma (~> 6.4)
72 96
   rack (~> 2.2)
73 97
   rake (~> 13.0)
74 98
   rspec (~> 3.9)
75
-  sassc (~> 2.2)
76 99
   sequel (~> 5.30)
77 100
   sinatra (~> 2.0)
78 101
   truncato (~> 0.7.11)
@@ -80,4 +103,4 @@ DEPENDENCIES
80 103
   webmock (~> 3.14)
81 104
 
82 105
 BUNDLED WITH
83
-   2.1.4
106
+   2.5.11

+ 2
- 4
Rakefile 查看文件

@@ -35,17 +35,15 @@ task 'scrape' do
35 35
 end
36 36
 
37 37
 task 'build' do
38
-  require 'sassc'
39
-
40 38
   unless Dir.exist?('./web/public')
41 39
     puts 'Creating web/public/'
42 40
     Dir.mkdir('./web/public')
43 41
   end
44 42
 
45
-  scss = File.read('./web/assets/style.scss')
46
-  css = SassC::Engine.new(scss, style: :compressed).render
43
+  css = File.read('./web/assets/style.css')
47 44
   puts 'Writing web/public/style.css'
48 45
   File.write('./web/public/style.css', css)
46
+
49 47
   js = File.read('./web/assets/script.js')
50 48
   puts 'Writing web/public/script.js'
51 49
   File.write('./web/public/script.js', js)

+ 2
- 0
db/connect.rb 查看文件

@@ -7,8 +7,10 @@ Dotenv.load(File.expand_path('../.env'))
7 7
 DB =
8 8
   Sequel.connect(
9 9
     adapter: :postgres,
10
+    host: ENV['DB_HOST'] || 'localhost',
10 11
     database: ENV['DB_DATABASE'],
11 12
     user: ENV['DB_USERNAME'],
12 13
     password: ENV['DB_PASSWORD'],
14
+    port: ENV['DB_PORT'] || 5432,
13 15
     logger: ENV['APP_ENV'] == 'development' ? Logger.new('db/log') : nil
14 16
   )

+ 2
- 2
lib/search.rb 查看文件

@@ -57,7 +57,7 @@ end
57 57
 def search_threads(q, username, from_date, to_date, sort, offset, exact_match)
58 58
   sort = Sequel.desc(sort == 'post' ? :last_post_created_at : :created_at)
59 59
   query = VLV::Thread
60
-    .select(Sequel.lit('threads.*, count(*) OVER() AS full_count'))
60
+    .select(Sequel.lit('threads.*'))
61 61
     .where(Sequel.lit("(LOWER(threads.creator) = LOWER(?) OR ? = '')", username, username))
62 62
     .where(Sequel.lit("created_at >= ? OR ? IS NULL", from_date, from_date))
63 63
     .where(Sequel.lit("created_at >= ? OR ? IS NULL", to_date, to_date))
@@ -74,7 +74,7 @@ end
74 74
 
75 75
 def search_posts(q, username, from_date, to_date, offset, exact_match)
76 76
   query = VLV::Post
77
-    .select(Sequel.lit('posts.*, threads.title as thread_title, threads.remote_id as remote_thread_id, count(*) OVER() AS full_count'))
77
+    .select(Sequel.lit('posts.*, threads.title as thread_title, threads.remote_id as remote_thread_id'))
78 78
     .join(Sequel.lit('threads on posts.thread_id = threads.id'))
79 79
     .where(Sequel.lit("(LOWER(posts.creator) = LOWER(?) OR (? = ''))", username, username))
80 80
     .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", from_date, from_date))

+ 1
- 1
spec/fetcher_spec.rb 查看文件

@@ -27,7 +27,7 @@ RSpec.describe Fetcher do
27 27
         result = subject.page(0)
28 28
         aggregate_failures do
29 29
           expect(result).to be_a(Nokogiri::HTML::Document)
30
-          expect(result.at_css('h3').text).to eq('VLV: politics, food, and aging')
30
+          expect(result.at_css('h3').text).to eq('VLV: Can we change the current header to something else')
31 31
           expect(result.css('.even, .odd').length).to eq(110)
32 32
         end
33 33
       end

+ 201
- 0
web/assets/style.css 查看文件

@@ -0,0 +1,201 @@
1
+* {
2
+  box-sizing: border-box;
3
+}
4
+
5
+html, body {
6
+  margin: 0;
7
+  padding: 0;
8
+}
9
+
10
+body {
11
+  font-family: verdana, sans-serif;
12
+}
13
+
14
+img {
15
+  max-width: 100%;
16
+}
17
+
18
+blockquote {
19
+  font-style: italic;
20
+  margin: 0;
21
+}
22
+
23
+.error {
24
+  color: #DD2222;
25
+}
26
+
27
+.container {
28
+  display: flex;
29
+  flex-direction: column;
30
+  margin: auto;
31
+  max-width: 800px;
32
+  min-height: 100vh;
33
+  padding: 15px;
34
+}
35
+
36
+.header__link {
37
+  color: black;
38
+  text-decoration: none;
39
+}
40
+
41
+.btn {
42
+  background-color: rgb(40, 96, 144);
43
+  border: 1px solid #222;
44
+  border-radius: 5px;
45
+  color: #ffffff;
46
+  cursor: pointer;
47
+  font-size: 20px;
48
+  padding: 0.5em 0.5em;
49
+  text-decoration: none;
50
+}
51
+
52
+.btn:hover {
53
+  background-color: rgb(30, 85, 135);
54
+}
55
+
56
+.btn--small {
57
+  font-size: 14px;
58
+}
59
+
60
+.btn--prev {
61
+  margin-right: 1em;
62
+}
63
+
64
+.center {
65
+  text-align: center;
66
+}
67
+
68
+.auth {
69
+  align-items: center;
70
+  display: flex;
71
+  font-size: 14px;
72
+  justify-content: space-between;
73
+}
74
+
75
+.auth__copy {
76
+  margin: 0;
77
+}
78
+
79
+.auth__username {
80
+  font-weight: bold;
81
+}
82
+
83
+.footer {
84
+  border-top: 1px solid black;
85
+  font-size: 12px;
86
+  margin: 20px 0;
87
+}
88
+
89
+.form {
90
+  display: flex;
91
+  flex-direction: column;
92
+  margin: 2em auto;
93
+  width: 100%;
94
+}
95
+
96
+.form__search {
97
+  border: 1px solid #999;
98
+  border-radius: 5px;
99
+  font-size: 20px;
100
+  padding: 0.5em;
101
+}
102
+
103
+.form .filters {
104
+  margin: 1em 0;
105
+}
106
+
107
+.filters__section {
108
+  display: flex;
109
+  padding: .5em 0;
110
+}
111
+
112
+.filters__subsection--sort {
113
+  visibility: hidden;
114
+}
115
+
116
+.filters__subsection--sort.open {
117
+  visibility: visible;
118
+}
119
+
120
+.filters__subsection {
121
+  flex: 1;
122
+}
123
+
124
+.filters__subsection--static {
125
+  flex: 1;
126
+}
127
+
128
+.filters__subsection:nth-child(2) {
129
+  padding: 0 1em;
130
+}
131
+
132
+.form__field {
133
+  margin: 10px 0;
134
+}
135
+
136
+.form__text-field {
137
+  border: 1px solid #000000;
138
+  border-radius: 4px;
139
+  font-size: 16px;
140
+  padding: 5px;
141
+  width: 100%;
142
+}
143
+
144
+.form__submit {
145
+  font-size: 16px;
146
+}
147
+
148
+.form--login {
149
+  margin-top: 0;
150
+}
151
+
152
+.form--login .form__label {
153
+  display: block;
154
+  margin: 10px 0;
155
+}
156
+
157
+.results-container {
158
+  padding-bottom: 1em;
159
+}
160
+
161
+.results__subheader {
162
+  border-bottom: 1px solid black;
163
+  margin: 1.5em 0;
164
+  padding: 5px 0;
165
+}
166
+
167
+.results__result {
168
+  background: #efefef;
169
+  border: 1px solid black;
170
+  border-radius: 5px;
171
+  margin: 1em 0;
172
+  padding: 0.5em;
173
+}
174
+
175
+.results__result.threads .result__info {
176
+  margin-bottom: 0;
177
+}
178
+
179
+.result__info {
180
+  display: flex;
181
+  font-size: 12px;
182
+  justify-content: space-between;
183
+}
184
+
185
+@media (max-width: 500px) {
186
+  .result__info {
187
+    flex-direction: column;
188
+  }
189
+
190
+  .result__info span {
191
+    display: inline-block;
192
+    margin: 5px 0;
193
+  }
194
+
195
+  .filters__section {
196
+    flex-direction: column;
197
+  }
198
+
199
+  .filters__subsection:nth-child(2) {
200
+    padding: 0;
201
+  }

+ 0
- 5
web/assets/style.scss 查看文件

@@ -1,5 +0,0 @@
1
-@import './web/assets/styles/auth.scss';
2
-@import './web/assets/styles/form.scss';
3
-@import './web/assets/styles/global.scss';
4
-@import './web/assets/styles/results.scss';
5
-@import './web/assets/styles/footer.scss';

+ 0
- 14
web/assets/styles/auth.scss 查看文件

@@ -1,14 +0,0 @@
1
-.auth {
2
-  align-items: center;
3
-  display: flex;
4
-  font-size: 14px;
5
-  justify-content: space-between;
6
-}
7
-
8
-.auth__copy {
9
-  margin: 0;
10
-}
11
-
12
-.auth__username {
13
-  font-weight: bold;
14
-}

+ 0
- 5
web/assets/styles/footer.scss 查看文件

@@ -1,5 +0,0 @@
1
-.footer {
2
-  border-top: 1px solid black;
3
-  font-size: 12px;
4
-  margin: 20px 0;
5
-}

+ 0
- 76
web/assets/styles/form.scss 查看文件

@@ -1,76 +0,0 @@
1
-.form {
2
-  display: flex;
3
-  flex: 1;
4
-  flex-direction: column;
5
-  margin: 2em auto;
6
-  width: 100%;
7
-}
8
-
9
-.form__search {
10
-  border: 1px solid #999;
11
-  border-radius: 5px;
12
-  font-size: 20px;
13
-  padding: 0.5em;
14
-}
15
-
16
-.form .filters {
17
-  margin: 1em 0;
18
-}
19
-
20
-.filters__section {
21
-  display: flex;
22
-  padding: .5em 0;
23
-
24
-  @media(max-width: 768px) {
25
-    flex-direction: column;
26
-  }
27
-}
28
-
29
-.filters__subsection--sort {
30
-  visibility: hidden;
31
-}
32
-
33
-.filters__subsection--sort.open {
34
-  visibility: visible;
35
-}
36
-
37
-.filters__subsection {
38
-  flex: 1;
39
-
40
-  &.filters__subsection--static {
41
-    flex: 1;
42
-  }
43
-
44
-  &:nth-child(2) {
45
-    padding: 0 1em;
46
-
47
-    @media(max-width: 768px) {
48
-      padding: 0;
49
-    }
50
-  }
51
-}
52
-
53
-.form__field {
54
-  margin: 10px 0;
55
-}
56
-
57
-.form__text-field {
58
-  border: 1px solid #000000;
59
-  border-radius: 4px;
60
-  font-size: 16px;
61
-  padding: 5px;
62
-  width: 100%;
63
-}
64
-
65
-.form__submit {
66
-  font-size: 16px;
67
-}
68
-
69
-.form--login {
70
-  margin-top: 0;
71
-}
72
-
73
-.form--login .form__label {
74
-  display: block;
75
-  margin: 10px 0;
76
-}

+ 0
- 62
web/assets/styles/global.scss 查看文件

@@ -1,62 +0,0 @@
1
-* {
2
-  box-sizing: border-box;
3
-}
4
-
5
-html, body {
6
-  margin: 0;
7
-  padding: 0;
8
-}
9
-
10
-body {
11
-  font-family: verdana, sans-serif;
12
-}
13
-
14
-img {
15
-  max-width: 100%;
16
-}
17
-
18
-blockquote {
19
-  font-style: italic;
20
-  margin: 0;
21
-}
22
-
23
-.error {
24
-  color: #DD2222;
25
-}
26
-
27
-.container {
28
-  display: flex;
29
-  flex-direction: column;
30
-  margin: auto;
31
-  max-width: 800px;
32
-  min-height: 100vh;
33
-  padding: 15px;
34
-}
35
-
36
-.header__link {
37
-  color: black;
38
-  text-decoration: none;
39
-}
40
-
41
-.btn {
42
-  background-color: rgb(40, 96, 144);
43
-  border: 1px solid #222;
44
-  border-radius: 5px;
45
-  color: #ffffff;
46
-  cursor: pointer;
47
-  font-size: 20px;
48
-  padding: 0.5em 0.5em;
49
-  text-decoration: none;
50
-}
51
-
52
-.btn:hover {
53
-  background-color: rgb(30, 85, 135);
54
-}
55
-
56
-.btn--small {
57
-  font-size: 14px;
58
-}
59
-
60
-.center {
61
-  text-align: center;
62
-}

+ 0
- 40
web/assets/styles/results.scss 查看文件

@@ -1,40 +0,0 @@
1
-.results-container {
2
-  padding-bottom: 1em;
3
-}
4
-
5
-.results__subheader {
6
-  border-bottom: 1px solid black;
7
-  margin: 1.5em 0;
8
-  padding: 5px 0;
9
-}
10
-
11
-.results__result {
12
-  background: #efefef;
13
-  border: 1px solid black;
14
-  border-radius: 5px;
15
-  margin: 1em 0;
16
-  padding: 0.5em;
17
-}
18
-
19
-.results__result.threads .result__info {
20
-  margin-bottom: 0;
21
-}
22
-
23
-.result__info {
24
-  display: flex;
25
-  font-size: 12px;
26
-  justify-content: space-between;
27
-
28
-  @media (max-width: 500px) {
29
-    flex-direction: column;
30
-
31
-    span {
32
-      display: inline-block;
33
-      margin: 5px 0;
34
-    }
35
-  }
36
-}
37
-
38
-.btn--prev {
39
-  margin-right: 1em;
40
-}

+ 0
- 1
web/server.rb 查看文件

@@ -45,7 +45,6 @@ class VLVSearch < Sinatra::Base
45 45
       erb :results, { locals: {errors: results[:errors]}, layout: :layout }
46 46
     else
47 47
       params[:current_count] = results[:results].to_a.size
48
-      params[:full_count] = results[:results].empty? ? 0 : results[:results].first[:full_count]
49 48
       previous_url, next_url = build_urls(params)
50 49
 
51 50
       locals =

Loading…
取消
儲存