From b7c5853de5f0f04625eab6389cba9de8b02e48fb Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Mon, 12 May 2025 14:53:31 -0400 Subject: Added streams index --- app/assets/stylesheets/main/entries.scss | 43 ++++++++++++++++++++++ app/controllers/blogs_controller.rb | 11 ++---- app/controllers/streams_controller.rb | 4 ++ app/helpers/application_helper.rb | 11 ++++++ app/models/stream.rb | 11 ++++++ app/models/update.rb | 8 ++++ app/views/streams/_stream.html.haml | 6 +-- app/views/streams/index.html.haml | 19 ++++++++++ app/views/streams/show.html.haml | 2 +- config/routes.rb | 1 + .../20250512181245_add_latest_post_at_to_stream.rb | 21 +++++++++++ db/schema.rb | 3 +- 12 files changed, 126 insertions(+), 14 deletions(-) create mode 100644 app/views/streams/index.html.haml create mode 100644 db/migrate/20250512181245_add_latest_post_at_to_stream.rb diff --git a/app/assets/stylesheets/main/entries.scss b/app/assets/stylesheets/main/entries.scss index 6ccaf7e..d67ae67 100644 --- a/app/assets/stylesheets/main/entries.scss +++ b/app/assets/stylesheets/main/entries.scss @@ -472,3 +472,46 @@ .next-post { float: right; } + +#streams-index { + width: 100%; + border-collapse: collapse; + + #streams-index-header-row { + th { + background-color: #bdbdbd; + padding-left: 0.5em; + border-top: 1px solid #848484; + border-bottom: 1px solid #848484; + } + } + + th { + padding-bottom: 0.5em; + padding-top: 0.5em; + text-align: left; + } + + td { + padding-top: 1em; + padding-left: 0.5em; + + time { + font-size: .75em; + } + + .stream-link { + font-weight: bold; + text-decoration: none; + + &, &:visited { + color: #ee2c2c; + } + + &:hover { + text-decoration: underline; + color: #9ea1ad; + } + } + } +} diff --git a/app/controllers/blogs_controller.rb b/app/controllers/blogs_controller.rb index 4f6d9ce..6e80754 100644 --- a/app/controllers/blogs_controller.rb +++ b/app/controllers/blogs_controller.rb @@ -1,12 +1,7 @@ -require 'redcarpet/render_strip' -class StrippedSummary < Redcarpet::Render::StripDown - def block_html(raw_html) - nil - end -end class BlogsController < ApplicationController + include ApplicationHelper def summary @blogs = Blog.where(published: true).order(published_at: :desc).paginate(page: params[:page], per_page: 10) @@ -33,12 +28,12 @@ class BlogsController < ApplicationController @prev = @blog.prev @next = @blog.next - body = Redcarpet::Markdown.new(StrippedSummary).render(@blog.body) + body = stripped_markdown(@blog.body) set_meta_tags(og: { title: @blog.title, type: "article", - description: (body.length <= 300 ? body : body[0..299]), + description: body[0, 299], url: blog_url(@blog, host: "www.fourisland.com"), article: { published_time: @blog.published_at.iso8601, diff --git a/app/controllers/streams_controller.rb b/app/controllers/streams_controller.rb index 9b7588c..aa81ab1 100644 --- a/app/controllers/streams_controller.rb +++ b/app/controllers/streams_controller.rb @@ -1,5 +1,9 @@ class StreamsController < ApplicationController + def index + @streams = Stream.order(latest_post_at: :desc).paginate(page: params[:page], per_page: 10) + end + def show @stream = Stream.find_by_slug(params[:slug]) @updates = @stream.updates.paginate(page: params[:page], per_page: 10) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 97a897f..a51f1a1 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,6 +1,7 @@ require 'redcarpet' require 'rouge' require 'rouge/plugins/redcarpet' +require 'redcarpet/render_strip' module ApplicationHelper @@ -45,4 +46,14 @@ module ApplicationHelper ] end + class StrippedSummary < Redcarpet::Render::StripDown + def block_html(raw_html) + nil + end + end + + def stripped_markdown(text) + Redcarpet::Markdown.new(StrippedSummary).render(text) + end + end diff --git a/app/models/stream.rb b/app/models/stream.rb index 0773143..6a738e2 100644 --- a/app/models/stream.rb +++ b/app/models/stream.rb @@ -8,11 +8,22 @@ class Stream < ApplicationRecord validates :title, presence: true validates :slug, presence: true, format: /\A[-a-z0-9]+\z/ + before_create :set_post_timestamp + def path "/thinks/#{slug}" end + def to_param + slug + end + def taggable self end + + private + def set_post_timestamp + self.latest_post_at = self.created_at + end end diff --git a/app/models/update.rb b/app/models/update.rb index 01907d8..a98a5d4 100644 --- a/app/models/update.rb +++ b/app/models/update.rb @@ -5,6 +5,8 @@ class Update < ApplicationRecord validates :stream, :body, presence: true + after_create :set_latest_timestamp + def path "/thinks/#{stream.slug}\#update-#{id}" end @@ -12,4 +14,10 @@ class Update < ApplicationRecord def taggable stream end + + private + def set_latest_timestamp + self.stream.latest_post_at = self.created_at + self.stream.save! + end end diff --git a/app/views/streams/_stream.html.haml b/app/views/streams/_stream.html.haml index 4a6b1e9..97d4813 100644 --- a/app/views/streams/_stream.html.haml +++ b/app/views/streams/_stream.html.haml @@ -2,9 +2,7 @@ %h2#stream-title= stream.title - unless stream.body.blank? %header#stream-intro.entry-content= markdown(stream.body) - - if stream.updates.size > 10 - = will_paginate @updates + = will_paginate @updates - unless @updates.empty? = render @updates - - if stream.updates.size > 10 - = will_paginate @updates + = will_paginate @updates diff --git a/app/views/streams/index.html.haml b/app/views/streams/index.html.haml new file mode 100644 index 0000000..bf5073f --- /dev/null +++ b/app/views/streams/index.html.haml @@ -0,0 +1,19 @@ +%table#streams-index + %tr#streams-index-header-row + %th Stream Topic + %th Updates + %th Last Post + - @streams.each do |stream| + %tr + %td + = link_to stream.title, stream, class: "stream-link" + %br + %time= stream.created_at.strftime("%B #{stream.created_at.day.ordinalize}, %Y at %-I:%M:%S%P") + %td= stream.updates.size + %td + - unless stream.updates.empty? + - latest_post = stream.updates.order(created_at: :desc).first + = link_to (stripped_markdown(latest_post.body)[0, 30] + "..."), stream + %br + %time= latest_post.created_at.strftime("%B #{latest_post.created_at.day.ordinalize}, %Y at %-I:%M:%S%P") += will_paginate @streams diff --git a/app/views/streams/show.html.haml b/app/views/streams/show.html.haml index 8365556..8d58f62 100644 --- a/app/views/streams/show.html.haml +++ b/app/views/streams/show.html.haml @@ -1,3 +1,3 @@ - title @stream.title -.breadcrumb= link_to "← Back to home page", root_path +.breadcrumb= link_to "← Back to streams", streams_path = render @stream diff --git a/config/routes.rb b/config/routes.rb index 9e62ebb..ad66501 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -56,6 +56,7 @@ Rails.application.routes.draw do end end + get 'thinks', to: 'streams#index', as: :streams get 'thinks/:slug', to: 'streams#show', as: :stream get 'plays', to: 'games#index' diff --git a/db/migrate/20250512181245_add_latest_post_at_to_stream.rb b/db/migrate/20250512181245_add_latest_post_at_to_stream.rb new file mode 100644 index 0000000..9d753e3 --- /dev/null +++ b/db/migrate/20250512181245_add_latest_post_at_to_stream.rb @@ -0,0 +1,21 @@ +class AddLatestPostAtToStream < ActiveRecord::Migration[7.1] + def up + add_column :streams, :latest_post_at, :datetime + + Stream.all.each do |stream| + if stream.updates.empty? + stream.latest_post_at = stream.created_at + else + stream.latest_post_at = stream.updates.order(created_at: :desc).first.created_at + end + + stream.save! + end + + change_column_null :streams, :latest_post_at, false + end + + def down + remove_column :streams, :latest_post_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index 795a986..76e9ad8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_01_12_025207) do +ActiveRecord::Schema[7.1].define(version: 2025_05_12_181245) do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -358,6 +358,7 @@ ActiveRecord::Schema[7.1].define(version: 2025_01_12_025207) do t.string "slug" t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false + t.datetime "latest_post_at", null: false end create_table "taggings", force: :cascade do |t| -- cgit 1.4.1