From bbf8dfc2e6fba66cc5b288e61a223a09591eeaaa Mon Sep 17 00:00:00 2001 From: songtianlun Date: Wed, 29 Jan 2025 01:53:50 +0800 Subject: [PATCH 1/5] feat: add watermarking functionality to weather art - Include the image_processing gem to handle image manipulation - Create a background worker for adding watermarks to weather art images - Update WeatherArt model to attach watermark images - Add a new watermark image asset This commit enhances the WeatherArt feature by allowing images to have watermarks added asynchronously, improving the visual presentation of the art. It ensures sufficient image dimensions before processing and includes error handling for the worker. --- Gemfile | 2 + Gemfile.lock | 9 +++ .../today_ai_weather_copyright_watermark1.png | Bin 0 -> 6033 bytes app/models/weather_art.rb | 1 + .../add_watermark_to_weatherart_worker.rb | 53 ++++++++++++++++++ 5 files changed, 65 insertions(+) create mode 100644 app/assets/images/today_ai_weather_copyright_watermark1.png create mode 100644 app/workers/add_watermark_to_weatherart_worker.rb diff --git a/Gemfile b/Gemfile index 1d6c1bc..b75cd2b 100644 --- a/Gemfile +++ b/Gemfile @@ -60,6 +60,8 @@ gem "aws-sdk-s3", "~> 1.177" gem "sidekiq", "~> 7.3" gem "sidekiq-scheduler", "~> 5.0" +gem "image_processing", "~> 1.13" + group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem gem "debug", platforms: %i[ mri windows ], require: "debug/prelude" diff --git a/Gemfile.lock b/Gemfile.lock index 30d3377..9ff2d31 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -164,6 +164,7 @@ GEM multipart-post (~> 2.0) faraday-net_http (3.4.0) net-http (>= 0.5.0) + ffi (1.17.1-arm64-darwin) formtastic (5.0.0) actionpack (>= 6.0.0) formtastic_i18n (0.7.0) @@ -183,6 +184,9 @@ GEM multi_xml (>= 0.5.2) i18n (1.14.6) concurrent-ruby (~> 1.0) + image_processing (1.13.0) + mini_magick (>= 4.9.5, < 5) + ruby-vips (>= 2.0.17, < 3) inherited_resources (1.14.0) actionpack (>= 6.0) has_scope (>= 0.6) @@ -240,6 +244,7 @@ GEM matrix (0.4.2) meta-tags (2.22.1) actionpack (>= 6.0.0, < 8.1) + mini_magick (4.13.2) mini_mime (1.1.5) minitest (5.25.4) msgpack (1.7.5) @@ -386,6 +391,9 @@ GEM faraday (>= 1) faraday-multipart (>= 1) ruby-progressbar (1.13.0) + ruby-vips (2.2.2) + ffi (~> 1.12) + logger ruby2_keywords (0.0.5) rubyzip (2.4.1) rufus-scheduler (3.9.2) @@ -502,6 +510,7 @@ DEPENDENCIES down (~> 5.4) friendly_id (~> 5.5) httparty (~> 0.22.0) + image_processing (~> 1.13) jbuilder jsbundling-rails kamal diff --git a/app/assets/images/today_ai_weather_copyright_watermark1.png b/app/assets/images/today_ai_weather_copyright_watermark1.png new file mode 100644 index 0000000000000000000000000000000000000000..47c2ce959346723e24fb1d0f93de116a043a02a7 GIT binary patch literal 6033 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 e + Rails.logger.error "Error adding watermark to WeatherArt #{weather_art_id}: #{e.message}" + Rails.logger.error e.backtrace.join("\n") + end + + private + + attr_reader :weather_art + + def add_watermark + return if weather_art.image_with_watermark.attached? + + watermark_path = Rails.root.join("app/assets/images/today_ai_weather_copyright_watermark1.png") + return unless File.exist?(watermark_path) + + image_tempfile = nil + watermark_tempfile = nil + begin + image_tempfile = weather_art.image.download + return unless image_dimensions_are_sufficient?(image_tempfile.path) + + image = ImageProcessing::Vips.source(image_tempfile.path) + watermark = ImageProcessing::Vips.source(watermark_path) + watermarked_image = image.composite(watermark, "overlay") + watermark_tempfile = Tempfile.new([ "watermarked_image", ".png" ]) + watermarked_image.write_to_file(watermark_tempfile.path) + weather_art.image_with_watermark.attach( + io: File.open(watermark_tempfile.path), + filename: "#{generate_filename("watermarked")}", + content_type: "image/png" + ) + ensure + watermark_tempfile.unlink if watermark_tempfile + end + end + + def image_dimensions_are_sufficient?(image_path) + dimensions = ImageProcessing::Vips.source(image_path).sizes + dimensions.width >= 200 && dimensions.height >= 200 + end + + def generate_filename(prefix) + "#{prefix}_#{weather_art.image.filename.base}" + end +end From 0352923c5b2f8df507b12ed9a875e4fbab69da84 Mon Sep 17 00:00:00 2001 From: songtianlun Date: Fri, 31 Jan 2025 10:46:32 +0800 Subject: [PATCH 2/5] feat: update weather data report format - Include actual update time in weather report - Rename watermark worker file for clarity This commit enhances the weather data report by updating the format to include the actual update time retrieved from the weather service API. Additionally, the watermark worker file has been renamed to improve readability and consistency in the naming convention. --- app/services/ai_service.rb | 2 +- app/services/weather_service.rb | 3 ++- ...herart_worker.rb => add_watermark_to_weather_art_worker.rb} | 0 3 files changed, 3 insertions(+), 2 deletions(-) rename app/workers/{add_watermark_to_weatherart_worker.rb => add_watermark_to_weather_art_worker.rb} (100%) diff --git a/app/services/ai_service.rb b/app/services/ai_service.rb index 39ee6c3..a9abdfa 100644 --- a/app/services/ai_service.rb +++ b/app/services/ai_service.rb @@ -50,7 +50,7 @@ class AiService - Temperature: #{weather_data[:temperature]}°C - Weather: #{weather_data[:description]} - Cloud cover: #{weather_data[:cloud]}% - - Time: Early morning + - Time: #{weather_data[:time]} Requirements: - Feature iconic landmarks or architecture from #{city.name} diff --git a/app/services/weather_service.rb b/app/services/weather_service.rb index da1e340..e350891 100644 --- a/app/services/weather_service.rb +++ b/app/services/weather_service.rb @@ -31,7 +31,8 @@ class WeatherService pressure: data["pressure"].to_f, visibility: data["vis"].to_f, cloud: data["cloud"].to_f, - description: data["text"] + description: data["text"], + time: response["updateTime"] } end end diff --git a/app/workers/add_watermark_to_weatherart_worker.rb b/app/workers/add_watermark_to_weather_art_worker.rb similarity index 100% rename from app/workers/add_watermark_to_weatherart_worker.rb rename to app/workers/add_watermark_to_weather_art_worker.rb From 905ec35fd8a678ff280c9bdf2842e43af77c5222 Mon Sep 17 00:00:00 2001 From: songtianlun Date: Sat, 1 Feb 2025 14:19:19 +0800 Subject: [PATCH 3/5] feat: add photo swipe lightbox functionality - Integrate PhotoSwipe library for enhanced image viewing - Create PhotoSwipeLightBoxController to manage images - Register lightbox controller in Stimulus framework - Update views to include lightbox functionality - Modify styles to accommodate new design elements This commit introduces a new way for users to view images with PhotoSwipe, improving the interactivity of the photo gallery. It also includes adjustments to the layout and styles for better presentation and user experience. --- Gemfile.lock | 7 + .../stylesheets/application.tailwind.css | 1 + app/javascript/application.js | 1 + app/javascript/controllers/index.js | 6 + .../photo_swipe_lightbox_controller.js | 42 ++++ app/models/weather_art.rb | 4 + app/views/layouts/application.html.erb | 22 +- app/views/weather_arts/_weather_stat.html.erb | 11 - .../weather_arts/_weather_stats.html.erb | 37 ++++ app/views/weather_arts/show.html.erb | 199 ++++++------------ package.json | 1 + yarn.lock | 16 +- 12 files changed, 183 insertions(+), 164 deletions(-) create mode 100644 app/javascript/controllers/photo_swipe_lightbox_controller.js delete mode 100644 app/views/weather_arts/_weather_stat.html.erb create mode 100644 app/views/weather_arts/_weather_stats.html.erb diff --git a/Gemfile.lock b/Gemfile.lock index 9ff2d31..c488385 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -164,7 +164,14 @@ GEM multipart-post (~> 2.0) faraday-net_http (3.4.0) net-http (>= 0.5.0) + ffi (1.17.1-aarch64-linux-gnu) + ffi (1.17.1-aarch64-linux-musl) + ffi (1.17.1-arm-linux-gnu) + ffi (1.17.1-arm-linux-musl) ffi (1.17.1-arm64-darwin) + ffi (1.17.1-x86_64-darwin) + ffi (1.17.1-x86_64-linux-gnu) + ffi (1.17.1-x86_64-linux-musl) formtastic (5.0.0) actionpack (>= 6.0.0) formtastic_i18n (0.7.0) diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css index 312a4fc..bc471f7 100644 --- a/app/assets/stylesheets/application.tailwind.css +++ b/app/assets/stylesheets/application.tailwind.css @@ -1,3 +1,4 @@ +@import "photoswipe/dist/photoswipe.css"; @tailwind base; @tailwind components; diff --git a/app/javascript/application.js b/app/javascript/application.js index 1aad597..63ba9e1 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -1,5 +1,6 @@ // Entry point for the build script in your package.json import "@hotwired/turbo-rails" +import "@hotwired/stimulus" import "@fontsource/playfair-display/400.css"; import "@fontsource/playfair-display/700.css"; import "@fontsource/raleway/400.css"; diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index d0685d3..40cfc50 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -6,3 +6,9 @@ import { application } from "./application" import HelloController from "./hello_controller" application.register("hello", HelloController) + +import PhotoSwipeLightBoxController from "./photo_swipe_lightbox_controller" + +console.log("ready to register photo-swipe") +application.register("photo-swipe-lightbox", PhotoSwipeLightBoxController) +console.log("successful to register photo-swipe") diff --git a/app/javascript/controllers/photo_swipe_lightbox_controller.js b/app/javascript/controllers/photo_swipe_lightbox_controller.js new file mode 100644 index 0000000..2dad88c --- /dev/null +++ b/app/javascript/controllers/photo_swipe_lightbox_controller.js @@ -0,0 +1,42 @@ +import { Controller } from "@hotwired/stimulus" +import PhotoSwipeLightbox from 'photoswipe/dist/photoswipe-lightbox.esm' +import PhotoSwipe from 'photoswipe/dist/photoswipe.esm' +import 'photoswipe/dist/photoswipe.css' + +export default class extends Controller { + static targets = ['image', 'gallery'] + + connect() { + this.initPhotoSwipeLightbox() + } + + initPhotoSwipeLightbox() { + const lightbox = new PhotoSwipeLightbox({ + gallery: this.galleryTarget, + children: 'a', + pswpModule: PhotoSwipe, + initialZoomInEndEvent: 'mousedown', + dataSource: (items) => { + return items.map((item) => ({ + src: item.dataset.pswpSrc, + w: parseInt(item.dataset.pswpWidth, 10), + h: parseInt(item.dataset.pswpHeight, 10), + title: item.dataset.pswpCaption, + })) + }, + padding: { top: 0, bottom: 0, left: 0, right: 0 }, // 自定义图片与页面边界的填充 + closeOnScroll: false, + zoom: true, // 启用缩放功能 + bgOpacity: 0.9, // 背景透明度 + pswpUIOptions: { + arrowPrev: true, + arrowNext: true, + zoom: true, // 添加缩放按钮 + fullscreen: true, // 添加全屏按钮 + counter: true, // 显示当前图片编号 + } + }) + lightbox.init() + // console.log('PhotoSwipeLightbox instance:', lightbox); + } +} \ No newline at end of file diff --git a/app/models/weather_art.rb b/app/models/weather_art.rb index 078a58e..f764058 100644 --- a/app/models/weather_art.rb +++ b/app/models/weather_art.rb @@ -51,4 +51,8 @@ class WeatherArt < ApplicationRecord Ahoy::Event.where("properties::jsonb->>'event_type' = 'weather_art_view' AND (properties::jsonb->>'weather_art_id')::integer = ?", self.id).count end end + + def image_url + image.attached? ? image.blob : nil + end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index bf4b014..f468d23 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -33,22 +33,22 @@ <%# Includes all stylesheet files in app/assets/stylesheets %> <%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> - + - + - - + + - + + diff --git a/app/views/weather_arts/_weather_stat.html.erb b/app/views/weather_arts/_weather_stat.html.erb deleted file mode 100644 index 486975f..0000000 --- a/app/views/weather_arts/_weather_stat.html.erb +++ /dev/null @@ -1,11 +0,0 @@ - -
-
- - - -
<%= title %>
-
-
<%= value %>
-
<%= desc %>
-
\ No newline at end of file diff --git a/app/views/weather_arts/_weather_stats.html.erb b/app/views/weather_arts/_weather_stats.html.erb new file mode 100644 index 0000000..df082f5 --- /dev/null +++ b/app/views/weather_arts/_weather_stats.html.erb @@ -0,0 +1,37 @@ +<%# Partial _weather_stats.html.erb %> + +
+
Temperature
+
<%= weather_art.temperature %>°C
+
Feels like <%= weather_art.feeling_temp %>°C
+
+ +
+
Wind
+
<%= weather_art.wind_scale %>
+
<%= weather_art.wind_speed %> km/h
+
+ +
+
Humidity
+
<%= weather_art.humidity %>%
+
Relative humidity
+
+ +
+
Visibility
+
<%= weather_art.visibility %> km
+
Clear view distance
+
+ +
+
Pressure
+
<%= weather_art.pressure %> hPa
+
Atmospheric pressure
+
+ +
+
Cloud Cover
+
<%= weather_art.cloud %>%
+
Sky coverage
+
\ No newline at end of file diff --git a/app/views/weather_arts/show.html.erb b/app/views/weather_arts/show.html.erb index 4806f3d..ba9d2b0 100644 --- a/app/views/weather_arts/show.html.erb +++ b/app/views/weather_arts/show.html.erb @@ -4,155 +4,88 @@ <% end %> -
- - <% if @weather_art.image.attached? %> -
- <%= image_tag @weather_art.image, - class: "absolute w-full h-full object-cover scale-110 filter blur-2xl opacity-25" %> -
-
- <% end %> +
+
+
- -
- -
- <%= link_to city_path(@weather_art.city), - class: "btn btn-ghost btn-lg gap-2 bg-base-100/50 backdrop-blur-sm hover:bg-base-100/70 transition-all duration-300" do %> - - - - Back to <%= @weather_art.city.name %> - <% end %> -
+ +
+ <%= link_to city_path(@weather_art.city), + class: "btn btn-ghost btn-md gap-2 bg-base-200 hover:bg-base-300 transition-all duration-300" do %> + + + + Back to <%= @weather_art.city.name %> + <% end %> +
-
-
- -
-
- - - - <%= @weather_art.city.full_name %> -
+ +
+
-

- - Weather Art - -

+ + <% if @weather_art.image.attached? %> +
+ +
+ <% end %> -
-
- - - - <%= @weather_art.weather_date.strftime("%B %d, %Y") %> -
-
- - - - <%= @weather_art.weather_date.strftime("%H:%M") %> -
-
-
+ +
+
+

+ Weather Art +

- -
-
- <% if @weather_art.image.attached? %> - <%= image_tag @weather_art.image, - class: "w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" %> -
- <% end %> -
+
+
+ <%= @weather_art.weather_date.strftime("%B %d, %Y") %> +
+
+ <%= @weather_art.weather_date.strftime("%H:%M") %> +
+
-
-
-

+

<%= weather_description_icon(@weather_art.description) %> <%= @weather_art.description %>

-
- -
-
-
- <%= weather_stat_icon("temperature") %> -
Temperature
-
-
<%= @weather_art.temperature %>°C
-
Feels like <%= @weather_art.feeling_temp %>°C
-
- -
-
- <%= weather_stat_icon("wind") %> -
Wind
-
-
<%= @weather_art.wind_scale %>
-
<%= @weather_art.wind_speed %> km/h
-
- -
-
- <%= weather_stat_icon("humidity") %> -
Humidity
-
-
<%= @weather_art.humidity %>%
-
Relative humidity
-
- -
-
- <%= weather_stat_icon("visibility") %> -
Visibility
-
-
<%= @weather_art.visibility %> km
-
Clear view distance
-
- -
-
- <%= weather_stat_icon("pressure") %> -
Pressure
-
-
<%= @weather_art.pressure %> hPa
-
Atmospheric pressure
-
- -
-
- <%= weather_stat_icon("cloud") %> -
Cloud Cover
-
-
<%= @weather_art.cloud %>%
-
Sky coverage
-
-
- - -
-
-
- - - -

AI Prompt

-
-

- <%= @weather_art.prompt %> -

+
+ <%= render 'weather_stats', weather_art: @weather_art %>
+ + +
+
+ + + +

AI Prompt

+
+

+ <%= @weather_art.prompt %> +

+
\ No newline at end of file diff --git a/package.json b/package.json index 3f93649..8b11caf 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "autoprefixer": "^10.4.20", "jquery": "^3.7.1", "jquery-ui": "^1.14.1", + "photoswipe": "^5.4.4", "postcss": "^8.5.1", "sass": "^1.83.4", "tailwindcss": "^3.4.17" diff --git a/yarn.lock b/yarn.lock index 91e1d6e..29ceef2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -153,7 +153,7 @@ "@hotwired/stimulus@^3.2.2": version "3.2.2" - resolved "https://registry.npmjs.org/@hotwired/stimulus/-/stimulus-3.2.2.tgz" + resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.2.2.tgz#071aab59c600fed95b97939e605ff261a4251608" integrity sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A== "@hotwired/turbo-rails@^8.0.12": @@ -722,20 +722,13 @@ jiti@^1.21.6: resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz" integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== -jquery-ui@^1.13.3: +jquery-ui@^1.13.3, jquery-ui@^1.14.1: version "1.14.1" resolved "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.14.1.tgz" integrity sha512-DhzsYH8VeIvOaxwi+B/2BCsFFT5EGjShdzOcm5DssWjtcpGWIMsn66rJciDA6jBruzNiLf1q0KvwMoX1uGNvnQ== dependencies: jquery ">=1.12.0 <5.0.0" -jquery-ui@^1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.14.1.tgz#ba342ea3ffff662b787595391f607d923313e040" - integrity sha512-DhzsYH8VeIvOaxwi+B/2BCsFFT5EGjShdzOcm5DssWjtcpGWIMsn66rJciDA6jBruzNiLf1q0KvwMoX1uGNvnQ== - dependencies: - jquery ">=1.12.0 <5.0.0" - jquery-ujs@^1.2.2: version "1.2.3" resolved "https://registry.npmjs.org/jquery-ujs/-/jquery-ujs-1.2.3.tgz" @@ -853,6 +846,11 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +photoswipe@^5.4.4: + version "5.4.4" + resolved "https://registry.yarnpkg.com/photoswipe/-/photoswipe-5.4.4.tgz#e045dc036453493188d5c8665b0e8f1000ac4d6e" + integrity sha512-WNFHoKrkZNnvFFhbHL93WDkW3ifwVOXSW3w1UuZZelSmgXpIGiZSNlZJq37rR8YejqME2rHs9EhH9ZvlvFH2NA== + picocolors@^1, picocolors@^1.0.1, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" From 05449d1e7ff5a4838446744aa02d3427425f7bcc Mon Sep 17 00:00:00 2001 From: songtianlun Date: Sat, 1 Feb 2025 14:31:53 +0800 Subject: [PATCH 4/5] chore: update PhotoSwipe import paths - Change import for PhotoSwipeLightbox to 'photoswipe/lightbox' - Change import for PhotoSwipe to 'photoswipe' These updates reflect the new module structure of the PhotoSwipe library, ensuring that the controller utilizes the correct paths for improved functionality and maintainability. --- app/javascript/controllers/photo_swipe_lightbox_controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/controllers/photo_swipe_lightbox_controller.js b/app/javascript/controllers/photo_swipe_lightbox_controller.js index 2dad88c..4e67fd8 100644 --- a/app/javascript/controllers/photo_swipe_lightbox_controller.js +++ b/app/javascript/controllers/photo_swipe_lightbox_controller.js @@ -1,6 +1,6 @@ import { Controller } from "@hotwired/stimulus" -import PhotoSwipeLightbox from 'photoswipe/dist/photoswipe-lightbox.esm' -import PhotoSwipe from 'photoswipe/dist/photoswipe.esm' +import PhotoSwipeLightbox from 'photoswipe/lightbox' +import PhotoSwipe from 'photoswipe' import 'photoswipe/dist/photoswipe.css' export default class extends Controller { From 09b3f06ad423e12806378f5573fd609e86f234b6 Mon Sep 17 00:00:00 2001 From: songtianlun Date: Sat, 1 Feb 2025 14:45:17 +0800 Subject: [PATCH 5/5] style: adjust pagination button sizes - Change button classes from `btn` to `btn btn-xs` for all pagination buttons - Ensure consistent styling across all pagination elements These changes standardize the button sizes in the pagination component, improving the visual uniformity. The adjustment enhances user experience by making the pagination buttons more appropriately sized within the interface, without affecting functionality. --- app/views/shared/_pagination.html.erb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/views/shared/_pagination.html.erb b/app/views/shared/_pagination.html.erb index 3850813..f9a5b7e 100644 --- a/app/views/shared/_pagination.html.erb +++ b/app/views/shared/_pagination.html.erb @@ -12,7 +12,7 @@
<%= link_to url_for(page: 1, region: params[:region], country: params[:country], sort: params[:sort]), - class: "join-item btn #{collection.first_page? ? 'btn-disabled' : 'btn-ghost'}" do %> + class: "join-item btn btn-xs #{collection.first_page? ? 'btn-disabled' : 'btn-ghost'}" do %> @@ -20,7 +20,7 @@ <%= link_to url_for(page: collection.prev_page || 1, region: params[:region], country: params[:country], sort: params[:sort]), - class: "join-item btn #{collection.first_page? ? 'btn-disabled' : 'btn-ghost'}" do %> + class: "join-item btn btn-xs #{collection.first_page? ? 'btn-disabled' : 'btn-ghost'}" do %> @@ -33,35 +33,35 @@ <% if start_page > 1 %> <%= link_to 1, url_for(page: 1, region: params[:region], country: params[:country], sort: params[:sort]), - class: "join-item btn btn-ghost hover:bg-primary/5" %> + class: "join-item btn btn-xs btn-ghost hover:bg-primary/5" %> <% if start_page > 2 %> - + <% end %> <% end %> <% (start_page..end_page).each do |page| %> <% if page == collection.current_page %> - <% else %> <%= link_to page, url_for(page: page, region: params[:region], country: params[:country], sort: params[:sort]), - class: "join-item btn btn-ghost hover:bg-primary/5" %> + class: "join-item btn btn-xs btn-ghost hover:bg-primary/5" %> <% end %> <% end %> <% if end_page < collection.total_pages %> <% if end_page < collection.total_pages - 1 %> - + <% end %> <%= link_to collection.total_pages, url_for(page: collection.total_pages, region: params[:region], country: params[:country], sort: params[:sort]), - class: "join-item btn btn-ghost hover:bg-primary/5" %> + class: "join-item btn btn-xs btn-ghost hover:bg-primary/5" %> <% end %> <%= link_to url_for(page: collection.next_page || collection.total_pages, region: params[:region], country: params[:country], sort: params[:sort]), - class: "join-item btn #{collection.last_page? ? 'btn-disabled' : 'btn-ghost'}" do %> + class: "join-item btn btn-xs #{collection.last_page? ? 'btn-disabled' : 'btn-ghost'}" do %> @@ -69,7 +69,7 @@ <%= link_to url_for(page: collection.total_pages, region: params[:region], country: params[:country], sort: params[:sort]), - class: "join-item btn #{collection.last_page? ? 'btn-disabled' : 'btn-ghost'}" do %> + class: "join-item btn btn-xs #{collection.last_page? ? 'btn-disabled' : 'btn-ghost'}" do %>