]> gitweb.mndrdr.org Git - arelpe.git/commitdiff
Significant UI improvements
authorAidan Cornelius-Bell <[email protected]>
Wed, 8 Jan 2025 04:35:58 +0000 (15:05 +1030)
committerAidan Cornelius-Bell <[email protected]>
Wed, 8 Jan 2025 04:35:58 +0000 (15:05 +1030)
26 files changed:
app/assets/stylesheets/application.css
app/controllers/pubview_controller.rb
app/helpers/posts_helper.rb
app/services/markdown_renderer.rb
app/views/api_keys/index.html.erb
app/views/api_keys/new.html.erb
app/views/api_keys/show.html.erb
app/views/devise/registrations/new.html.erb
app/views/layouts/_alert.html.erb [new file with mode: 0644]
app/views/layouts/_home_post_links.html.erb
app/views/layouts/_navigation_buttons.html.erb
app/views/layouts/_post_navigation.html.erb [new file with mode: 0644]
app/views/layouts/application.html.erb
app/views/pages/edit.html.erb
app/views/pages/index.html.erb
app/views/pages/new.html.erb
app/views/pages/show.html.erb
app/views/posts/edit.html.erb
app/views/posts/index.html.erb
app/views/posts/new.html.erb
app/views/posts/show.html.erb
app/views/pubview/index.html.erb
app/views/pubview/post.html.erb
app/views/subscriptions/index.html.erb
app/views/user_manager/index.html.erb
app/views/user_manager/show.html.erb

index 082a088e0ce274e266b1468986926e1befa8e6d2..e21421a37ed36e6aaf3f9174274bbb48d8fbd8c0 100644 (file)
@@ -193,6 +193,23 @@ abbr {
     font-variant-emoji: unicode;
 }
 
+.text-indent {
+    text-indent: 2em;
+}
+
+.note {
+    border: 1px solid var(--accent-a);
+    border-radius: 3px;
+    padding: 4px 8px;
+}
+
+.reg-form {
+    border: 1px solid var(--accent-a);
+    border-radius: 3px;
+    padding: 4px 8px;
+    background: var(--quote-bg);
+}
+
 /* Style for all form inputs */
 input[type="text"],
 input[type="email"],
@@ -240,6 +257,15 @@ label {
     margin-top: -25px;
 }
 
+.post_siteheading {
+    color: var(--link-color);
+    margin-bottom: -0.5em;
+}
+
+.post_title {
+    margin-top: 0;
+}
+
 .post {
     background-color: var(--post-bg);
     padding: 2em;
@@ -458,7 +484,7 @@ ul .pinned::before {
     border-radius: 4px;
     padding: 1px 1.5em;
     margin: 10px auto;
-    max-width: 290px;
+    max-width: 690px;
     color: var(--accent-c);
 }
 
@@ -684,3 +710,127 @@ ul .post-item a:visited {
         transition: transform 0.2s ease;
     }
 }
+
+/* Margin Notes/Footnotes */
+/* Two-column layout */
+@media (min-width: 1024px) {
+    .post-grid {
+        display: grid;
+        grid-template-columns: minmax(0, 700px) minmax(0, 200px);
+        gap: 45px;
+        margin: 0 auto;
+    }
+
+    .main-content {
+        grid-column: 1;
+        position: relative;
+    }
+
+    .side-notes {
+        grid-column: 2;
+        position: relative;
+        height: 100%;
+    }
+
+    .side-note {
+        position: absolute;
+        width: 100%;
+        font-size: 0.9em;
+        color: var(--light-text);
+        padding: 0.5em;
+        border-left: 2px solid var(--accent-a);
+        background: var(--post-bg);
+        word-break: break-all;
+        transition:
+            border-color 0.2s,
+            background-color 0.2s;
+    }
+
+    .side-note a {
+        color: var(--light-text);
+        text-decoration: underline;
+        font-size: 0.9em;
+    }
+
+    .side-note:hover {
+        border-left-color: var(--link-color);
+        background-color: var(--quote-bg);
+    }
+
+    /* Style reference numbers in main text */
+    .main-content p a[rel="nofollow"] {
+        color: var(--accent-a);
+        text-decoration: none;
+    }
+}
+
+/* Mobile layout */
+@media (max-width: 1023px) {
+    .post-grid {
+        display: block;
+    }
+
+    .side-notes {
+        display: none;
+    }
+
+    /* Show original footnotes on mobile */
+    .main-content p[style*="display: none"] {
+        display: block !important;
+    }
+}
+
+/* Post Navigation */
+.post-navigation {
+    margin: 2em 0;
+    padding: 1.5em 0;
+    border-top: 1px solid var(--accent-a);
+}
+
+.nav-links {
+    display: flex;
+    justify-content: space-between;
+    gap: 1em;
+}
+
+.nav-previous,
+.nav-next {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    text-decoration: none;
+    color: var(--body-text);
+}
+
+.nav-next {
+    text-align: right;
+}
+
+.nav-label {
+    font-size: 0.9em;
+    color: var(--accent-a);
+}
+
+.nav-title {
+    font-weight: bold;
+    color: var(--link-color);
+}
+
+.nav-previous:hover .nav-title,
+.nav-next:hover .nav-title {
+    text-decoration: underline;
+}
+
+@media (max-width: 768px) {
+    .nav-links {
+        flex-direction: column;
+    }
+
+    .nav-next {
+        text-align: left;
+    }
+}
+
+.foot_separator {
+    margin-top: -1.5em;
+}
index 610aa747a8b6c11a14af9d73c55da504c2811d2e..64aabfa77c7691a072c5ffbd8408ba3b9f7c58de 100644 (file)
@@ -1,4 +1,5 @@
 class PubviewController < ApplicationController
+  include PostsHelper
   before_action :set_promo, only: [:index, :post]
 
   def index
@@ -42,6 +43,10 @@ class PubviewController < ApplicationController
       @excerpt = @post.generate_excerpt
       @tags = @post.format_tags
       @rendered_content = @post.rendered_content
+      # Get adjacent posts for navigation
+      adjacent = adjacent_posts(@post)
+      @previous_post = adjacent[:previous]
+      @next_post = adjacent[:next]
     else
       @missing = "post"
       render 'error/error', status: :not_found, missing: 'post'
index a7b8cec8987770c5862dea8bb15b71b91f7802d9..a94029188c3e85eacd8468e2a2bd5d488032fc90 100644 (file)
@@ -1,2 +1,14 @@
 module PostsHelper
+  def adjacent_posts(post)
+    {
+      previous: Post.dispatches
+                    .where('published_at < ?', post.published_at)
+                    .order(published_at: :desc)
+                    .first,
+      next: Post.dispatches
+              .where('published_at > ?', post.published_at)
+              .order(published_at: :asc)
+              .first
+    }
+  end
 end
index 5b04217aa7234a3f6fe7791de58d65720bed7703..712c59f258d5862a2ae9685177ea59cd834f1432 100644 (file)
@@ -1,23 +1,29 @@
 class MarkdownRenderer
   def self.render(text)
-       options = {
-         filter_html:     true,
-         hard_wrap:       true,
-         link_attributes: { rel: 'nofollow' },
-         space_after_headers: true,
-         fenced_code_blocks: true
-       }
+    options = {
+      filter_html:     false,
+      hard_wrap:       true,
+      link_attributes: { rel: 'nofollow' },
+      space_after_headers: true,
+      fenced_code_blocks: true
+    }
 
-       extensions = {
-         autolink:           true,
-         superscript:        true,
-         disable_indented_code_blocks: true,
-         highlight: true
-       }
+    extensions = {
+      autolink:           true,
+      superscript:        true,
+      disable_indented_code_blocks: true,
+      highlight: true
+    }
 
-       renderer = Redcarpet::Render::HTML.new(options)
-       markdown = Redcarpet::Markdown.new(renderer, extensions)
+    # Just wrap the content in our grid containers
+    renderer = Redcarpet::Render::HTML.new(options)
+    markdown = Redcarpet::Markdown.new(renderer, extensions)
 
-       markdown.render(text)
+    '<div class="post-grid">' +
+    '<div class="main-content">' +
+    markdown.render(text) +
+    '</div>' +
+    '<div class="side-notes"></div>' +
+    '</div>'
   end
-end
\ No newline at end of file
+end
index 4e56a553e551bd6a805890cac53a98cc2be27af8..72bec46bf80c8c2132cb80572e08a597091c74fc 100644 (file)
@@ -4,6 +4,10 @@
 <%= link_to 'New API Key', new_api_key_path, class: "button" %>
 <%= link_to 'Home', root_path, class: "button" %>
 </div>
+
+<%= render partial: "layouts/alert" %>
+
+
 <div class="post">
        <div class="container">
                <table>
@@ -28,4 +32,4 @@
                </tbody>
          </table>
        </div>
-</div>
\ No newline at end of file
+</div>
index 78e525050b73bd72870360fa63fbae83196a4923..d9bae94e92afc672f57020a4b907a357af06c1d4 100644 (file)
@@ -3,15 +3,17 @@
        <%= link_to 'Back to API Keys', api_keys_path, class: "button" %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <div class="post">
        <div class="container">
                <p>Click the button below to generate a new API key.</p>
-               
+
                <%= form_with(model: @api_key, local: true) do |form| %>
                <% if @api_key.errors.any? %>
                        <div id="error_explanation">
                        <h2><%= pluralize(@api_key.errors.count, "error") %> prohibited this API key from being saved:</h2>
-               
+
                        <ul>
                                <% @api_key.errors.full_messages.each do |message| %>
                                <li><%= message %></li>
                        </ul>
                        </div>
                <% end %>
-               
+
                <div class="actions">
                        <%= form.submit "Generate API Key" %>
                </div>
                <% end %>
        </div>
-</div>
\ No newline at end of file
+</div>
index 33efe6e0de97e6531cf21bb43ab523da2f2fde18..17b741163fadaa4382ae233ae6a3ea7c78f7fb24 100644 (file)
@@ -3,13 +3,15 @@
        <%= link_to 'Back to API Keys', api_keys_path, class: "button" %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <div class="post">
        <div class="container">
                <p>
                <strong>Key:</strong>
                <%= @api_key.key %>
                </p>
-               
+
                <p>
                <strong>Created at:</strong>
                <%= @api_key.created_at %>
index 6cfcf9f588f34644f680d10804f1f9569b55c121..03fd1205e310df69fab946d7c96d1b129f6adc63 100644 (file)
@@ -2,44 +2,48 @@
 <% content_for :form_content do %>
   <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
     <%= render "devise/shared/error_messages", resource: resource %>
-    
-    <%= image_tag "aidan_about_u.svg", class: "aidan_about_u", alt: "To get started, tell me about yourself:" %>
-    
-    <div class="field-group">
-      <div class="field">
-        <%= f.label :first_name %>
-        <%= f.text_field :first_name, autofocus: true %>
-      </div>
-      <div class="field">
-        <%= f.label :last_name %>
-        <%= f.text_field :last_name %>
-      </div>
-    </div>
 
-    <div class="field">
-      <%= f.label :email %>
-      <%= f.email_field :email, autocomplete: "email" %>
-    </div>
+    <h4>Hello, I’m <a href="/about">Aidan</a>, it’s great to meet a likeminded human — </h4>
+        <p class="text-indent">↓ To get started, tell me briefly about yourself:</p>
+
+    <div class="reg-form">
+        <div class="field-group">
+        <div class="field">
+            <%= f.label :first_name %>
+            <%= f.text_field :first_name, autofocus: true, placeholder: "Jennifer" %>
+        </div>
+        <div class="field">
+            <%= f.label :last_name %>
+            <%= f.text_field :last_name, placeholder: "Davies" %>
+        </div>
+        </div>
 
-    <div class="field-group">
-      <div class="field">
-        <%= f.label :password %>
-        <%= f.password_field :password, autocomplete: "new-password", placeholder: @minimum_password_length ? "#{@minimum_password_length} characters minimum" : "" %>
-      </div>
-  
-      <div class="field">
-        <%= f.label :password_confirmation %>
-        <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
-      </div>
+        <div class="field">
+        <%= f.label :email %>
+        <%= f.email_field :email, autocomplete: "email", placeholder: "[email protected]" %>
+        </div>
+
+        <div class="field-group">
+        <div class="field">
+            <%= f.label :password %>
+            <%= f.password_field :password, autocomplete: "new-password", placeholder: @minimum_password_length ? "#{@minimum_password_length} characters minimum" : "" %>
+        </div>
+
+        <div class="field">
+            <%= f.label :password_confirmation %>
+            <%= f.password_field :password_confirmation, autocomplete: "new-password", placeholder: "Same one again..." %>
+        </div>
+        </div>
     </div>
-    
-    <%= image_tag "aidan_dispatches.svg", class: "aidan_about_u", alt: "Want new dispatches delivered right to you?" %>
-    
+
+    <h4>Now comes the choice of a lifetime</h4>
+    <p class="text-indent">↓ <em>Would you like dispatches delivered directly to your email?</em></p>
+
     <div class="field checkbox">
       <%= f.check_box :subscribe_to_newsletter %>
       <%= f.label :subscribe_to_newsletter, "I want to receive mind reader dispatches by email newsletter", id: "sub" %>
     </div>
-    <p>Note: you may be sent two confirmation emails – one to confirm your registration, one to confirm your mailing list preferences.</p>
+    <p class="note">⚠️ Note: if you opt-in to the email newsletter you will be sent <strong>two confirmation emails</strong> – one to confirm your registration, one to confirm your mailing list preferences – you’ll need to confirm both... sorry!</p>
 
     <% if Rails.env.production? %>
     <div class="field">
@@ -53,4 +57,4 @@
   <% end %>
 <% end %>
 
-<%= render template: 'layouts/user_page_template' %>
\ No newline at end of file
+<%= render template: 'layouts/user_page_template' %>
diff --git a/app/views/layouts/_alert.html.erb b/app/views/layouts/_alert.html.erb
new file mode 100644 (file)
index 0000000..5b661cf
--- /dev/null
@@ -0,0 +1,6 @@
+<% if notice or alert %>
+  <div class="notice">
+    <h3>Notice:</h3>
+    <p><%= notice or alert %></p>
+  </div>
+<% end %>
index f69f51996d6a127a13dea91725972201836abb74..0a9596eae7486b167fccb8f1755368c1efc620fb 100644 (file)
@@ -1,7 +1,6 @@
 <% if !@post&.short_dispatch? %>
 <% if @post&.title? %><h3>Follow via RSS, Email or Membership...</h3><% end %>
-<p><span class="callout">→ 📬 Want an email for each new post?</span> Join the mailing list for free <%= link_to "right here <abbr title=\"internal link\">&swarr;&#xFE0E;</abbr>".html_safe, "/join/" %>.</p>
-<p><span class="callout">→ 💰 Like this work and want to support it?</span> Get started <%= link_to " here <abbr title=\"internal link\">&swarr;&#xFE0E;</abbr>".html_safe, "/join/" %>.</p>
+<p><span class="callout">→ 📬 Join the community for free</span> receive an email with each new post, or optionally support this work financially <%= link_to "learn more here <abbr title=\"internal link\">&swarr;&#xFE0E;</abbr>".html_safe, "/join/" %>.</p>
 <p><span class="callout">→ 📰 Prefer RSS?</span> you can subscribe to a combined <%= link_to "bookmarks+dispatches feed here <abbr title=\"internal link\">&swarr;&#xFE0E;</abbr>".html_safe, rss_path %> or <%= link_to "full text dispatches only feed here <abbr title=\"external link\">&nearr;&#xFE0E;</abbr>".html_safe, dispatches_rss_path %>.</p>
 <% end %>
 <% if @post %>
index caa8ddc8873cfa0ddefffbd69b266fd317d7fde1..f8b299827fc8bc1b734b525196788fb94c38c3ab 100644 (file)
@@ -20,6 +20,8 @@
   <% end %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <script type="text/javascript">
 document.addEventListener('DOMContentLoaded', function() {
   // Create and insert the toggle button
diff --git a/app/views/layouts/_post_navigation.html.erb b/app/views/layouts/_post_navigation.html.erb
new file mode 100644 (file)
index 0000000..bc132a9
--- /dev/null
@@ -0,0 +1,17 @@
+<div class="post-navigation">
+  <div class="nav-links">
+    <% if @previous_post %>
+      <%= link_to public_post_path(@previous_post.published_at.year, @previous_post.slug), class: "nav-previous" do %>
+        <span class="nav-label">← Previous</span>
+        <span class="nav-title"><%= @previous_post.title %></span>
+      <% end %>
+    <% end %>
+
+    <% if @next_post %>
+      <%= link_to public_post_path(@next_post.published_at.year, @next_post.slug), class: "nav-next" do %>
+        <span class="nav-label">Next →</span>
+        <span class="nav-title"><%= @next_post.title %></span>
+      <% end %>
+    <% end %>
+  </div>
+</div>
index f4bc18fe02781a51e6819bcda58bad553f0a09bb..93378cb0d05d357a27ece123cf8a64de2a599672 100644 (file)
     <% if content_for?(:meta_keywords) %>
     <meta name="keywords" content="<%= yield(:meta_keywords) %>">
     <% end %>
-    
+
     <%= csrf_meta_tags %>
     <%= csp_meta_tag %>
 
     <%= stylesheet_link_tag "application" %>
-    
+
     <%= auto_discovery_link_tag(:rss, rss_url, title: "mind reader :: dispatches and bookmarks in summary") %>
     <%= auto_discovery_link_tag(:rss, dispatches_rss_url, title: "mind reader :: dispatches full text") %>
-    
+
     <% if ['posts', 'pages'].include?(controller.controller_name) %>
     <link rel="stylesheet" href="/simplemde.min.css">
     <script src="/simplemde.min.js"></script>
     <% end %>
   </head>
-  <% if !Rails.env.production? %>
-    <div class="marquee"><div class="track">NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD</div></div>
-  <% end %> 
-  <% if notice or alert %>
-    <div class="notice">
-      <h3>Notice:</h3>
-      <p><%= notice or alert %></p>
-    </div>
-  <% end %>
 
   <body>
-    <%= yield %>
+      <% if !Rails.env.production? %>
+        <div class="marquee"><div class="track">NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD NOT PROD</div></div>
+      <% end %>
+      <%= yield %>
 
     <footer>
       <p class="account"><% if current_user&.first_name? %>Welcome back, <%= link_to current_user.first_name, edit_user_registration_path %>. <% if current_user&.admin? %>You hold the keys to the kingdom.<% end %> <% if current_user&.paid_user? %> Thank you, your financial support makes this work possible.<% elsif current_user&.active_subscriber? %>Thank you for your ongoing support.<% end %><% else %> You are not logged in. <%= link_to "Change that?", new_user_session_path %><% end %></span></p>
index cae786a358ba0bbc89f6e611e1952814ccb3459d..802a054c445b47cb4bbfeb467f130983e4d54412 100644 (file)
@@ -5,4 +5,6 @@
   <%= link_to "Back to pages", pages_path, class: "button" %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <%= render "form", page: @page %>
index 0bd4b6b5cdcd5b61ce804a8e66895d55455aa981..b8d598a822c7ebbcd57c497736b577b754605035 100644 (file)
@@ -4,6 +4,8 @@
   <%= link_to "New page", new_page_path, class: "button" %> <%= link_to "Home", root_path, class: "button" %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <div class="post">
   <div class="container">
     <table>
@@ -37,4 +39,4 @@
   <div class="container">
     <%= paginate @pages %>
   </div>
-<% end %>
\ No newline at end of file
+<% end %>
index 274e43b57be5e8dca5a9c5ba2ae9348d96c194e0..d15dbc5c6fea238c17a5135861fa63e9a6245736 100644 (file)
@@ -4,5 +4,6 @@
   <%= link_to "Back to pages", pages_path, class: "button" %>
 </div>
 
-<%= render "form", page: @page %>
+<%= render partial: "layouts/alert" %>
 
+<%= render "form", page: @page %>
index 9d67ad1dbeafc90b9c71f8e8ed43415d49796ba3..582839d427cf27c511d8f9c627b6cf81f6bcffd7 100644 (file)
@@ -1,13 +1,15 @@
 <div class="container">
   <% content_for :title, "Viewing page" %>
   <h1>Page details</h1>
-  <%= link_to "Edit this page", edit_page_path(@page), class: "button" %> 
+  <%= link_to "Edit this page", edit_page_path(@page), class: "button" %>
   <%= link_to "Back to pages", pages_path, class: "button" %>
   <%= button_to "Destroy this page", @page, method: :delete %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <div class="post">
   <div class="container">
     <%= render @page %>
   </div>
-</div>
\ No newline at end of file
+</div>
index 08ed2bc81a5945fd693916c23f75b76ab0f7ec31..1493f906b1d0cadcd9034e70dc444e0e2c008494 100644 (file)
@@ -4,8 +4,10 @@
   <%= link_to "Back to posts", posts_path, class: "button" %> <%= link_to "Show this post", @post, class: "button" %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <div class="post">
   <div class="container">
     <%= render "form", post: @post %>
   </div>
-</div>
\ No newline at end of file
+</div>
index ce4c9c970bec742c6f2a44d39fbb73225b1e7f33..fe2f5bd1784a3464768d8e4361a370b3e7779354 100644 (file)
@@ -6,6 +6,8 @@
   <%= link_to "Import Data", importer_path, class: "button" %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <div class="post">
   <div class="container">
     <table>
index 90c4fcddb6ce84ee7add990355a8bb375e8a8a78..f9f4513e6f8ba0073570ee1da2f48dd2abf3e38e 100644 (file)
@@ -4,8 +4,10 @@
   <%= link_to "Back to posts", posts_path, class: "button" %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <div class="post">
-  <div class="container"> 
+  <div class="container">
     <%= render "form", post: @post %>
   </div>
 </div>
index 6ee72e715aaa1ee5de72931e5a33deb063cd1baf..d67eb2f70a35c866b15ac3c6ac8dc4adb45366b0 100644 (file)
@@ -1,3 +1,5 @@
+<%= render partial: "layouts/alert" %>
+
 <div class="container">
   <h1>Post details</h1>
   <%= link_to "Back to posts", posts_path, class: "button" %>
index ca19840df42bd71eac47f1f7027602855147a119..dc1e8814a46a6eff7c8563ee738f9f4229fca3ec 100644 (file)
               </blockquote>
             <% else %>
               <blockquote class="excerpt"><%= item.generate_excerpt %>...</blockquote>
-              <% if item.summary? && current_user.present? && (!current_user&.hide_ai_summaries?) %>
-              <blockquote class="excerpt">
-                  <span class="ai-summary"><abbr title="Machine learning summary via Kagi">ML</abbr> Summary</span><span class="ai-summary-block"><%= item.summary %>
-              </blockquote>
-              <% end %>
             <% end %>
           <% else %>
             <span class="post-link">
index 0268a68b2ba64c64d298a48a7d093c47849bff6b..37d1244c16896f8dcb4a8584c5ae5bf782d25d7e 100644 (file)
@@ -7,7 +7,8 @@
   <% content_for :meta_keywords, "#{@post.tags}" %>
   <% content_for :meta_published, "#{@post.created_at&.strftime('%Y-%m-%d')}" %>
   <% if @post.post_type != "bookmark" %>
-  <h1><%= @post.title %></h1>
+  <h3 class="post_siteheading">Aidan Cornelius-Bell’s mind reader:</h3>
+  <h1 class="post_title"><%= @post.title %></h1>
   <div class="bookmark-buttons">
       <%= link_to "↼ More dispatches 👀", "#{root_path}?filter=posts", class: "button button-bottomless" %>
       <% if !current_user %>
@@ -15,7 +16,7 @@
       <% end %>
   </div>
   <div class="postmeta">
-       <p >Posted <%= @post.published_at.strftime('%B %d, %Y') %> and tagged <%= raw @post.format_tags %><br><% if [email protected]_dispatch?%>Reading Time: about <%= @reading_time %> minute(s) <% end %> from: Aidan Cornelius-Bell.</p>
+       <p ><% if [email protected]_dispatch?%>About a <%= @reading_time %> minute read, p<% else %>P<% end %>osted <%= @post.published_at.strftime('%B %d, %Y') %> and tagged <%= raw @post.format_tags %></p>
   </div>
   <% else %>
   <h1 style="margin-bottom: -.8em">Bookmark comment permalink:</h1>
@@ -36,6 +37,9 @@
         <p class="lead"><%= @promo_strings.sample %> <%= link_to "Start right now!", join_path, class: "lead-button" %></p>
     <% end %>
        <%= raw @rendered_content %>
+
+ <%= render partial: "layouts/post_navigation" %>
+  <hr class="foot_separator">
   </div>
 </div>
 
   <%= render partial: "layouts/home_post_links" %>
 </div>
 <% end %>
+
+<script>
+document.addEventListener('DOMContentLoaded', function() {
+  if (window.innerWidth >= 1024) {
+    const mainContent = document.querySelector('.main-content');
+    const sideNotes = document.querySelector('.side-notes');
+
+    if (mainContent && sideNotes) {
+      // Find all the original footnotes first and store them
+      const footnotes = new Map();
+      const footnoteParagraphs = Array.from(mainContent.querySelectorAll('p'))
+        .filter(p => /^\[\d+\]/.test(p.textContent));
+
+      // Store footnotes and hide originals
+      footnoteParagraphs.forEach(p => {
+        const num = p.textContent.match(/^\[(\d+)\]/)[1];
+        footnotes.set(num, p.innerHTML);
+        p.style.display = 'none';
+      });
+
+      // Find and process reference markers in the main text
+      const paragraphs = Array.from(mainContent.querySelectorAll('p'))
+        .filter(p => !footnoteParagraphs.includes(p)); // Exclude footnote paragraphs
+
+      let lastBottom = 0;
+      const padding = 30; // Increased padding between notes
+
+      paragraphs.forEach(p => {
+        const markers = Array.from(p.textContent.matchAll(/\[(\d+)\]/g));
+        markers.forEach(match => {
+          const num = match[1];
+          if (footnotes.has(num)) {
+            const noteContent = footnotes.get(num);
+            const noteDiv = document.createElement('div');
+            noteDiv.className = 'side-note';
+            noteDiv.innerHTML = noteContent;
+            sideNotes.appendChild(noteDiv);
+
+            // Get the position of the reference
+            const text = p.textContent;
+            const referencePosition = text.indexOf(`[${num}]`);
+            const textBefore = text.substring(0, referencePosition);
+            const tempSpan = document.createElement('span');
+            tempSpan.textContent = textBefore;
+            p.insertBefore(tempSpan, p.firstChild);
+            const spanRect = tempSpan.getBoundingClientRect();
+            p.removeChild(tempSpan);
+
+            // Calculate position
+            const pRect = p.getBoundingClientRect();
+            const containerRect = mainContent.getBoundingClientRect();
+            let proposedTop = pRect.top - containerRect.top +
+              (referencePosition > 0 ? spanRect.height : 0);
+
+            // Ensure no overlap
+            proposedTop = Math.max(proposedTop, lastBottom + padding);
+
+            noteDiv.style.top = `${proposedTop}px`;
+
+            // Update lastBottom after the note is rendered
+            const noteRect = noteDiv.getBoundingClientRect();
+            lastBottom = proposedTop + noteRect.height;
+          }
+        });
+      });
+    }
+  }
+});
+</script>
index 886e5f2730531a9fdb27593622026904afcd1a93..04699dcc03d1b43cf2163b419eba2472747e4108 100644 (file)
@@ -15,7 +15,7 @@
        <% end %>
        <p>If you are a mailing list subscriber, <%= link_to "check that your premium status", mailing_lists_path %> has transferred so that you get bonus mail for premium members. Please be aware that data here are slightly delayed – don’t panic if things are not yet up to date!</p>
   </div>
-  
+
   <% if @portal_session %>
        <p>
          <%= link_to "Manage your subscription", @portal_session.url, class: "button", data: { turbo: false } %>
@@ -49,9 +49,9 @@
 
   <% if @subscription_status != 'active' %>
        <div class="subscription-actions">
-         <%= link_to "Subscribe", new_subscription_path, class: "button primary" %>
+         <%= link_to "Become a supporter", new_subscription_path, class: "button primary" %>
        </div>
   <% end %>
 <% end %>
 
-<%= render template: 'layouts/user_page_template' %>
\ No newline at end of file
+<%= render template: 'layouts/user_page_template' %>
index 6965bcc69a1ec621e1d450bd5e71a111c41d4256..0dcf92bbda1755cd1da720be03de389a425dbd59 100644 (file)
@@ -36,4 +36,4 @@
        </tbody>
        </table>
   </div>
-</div>
\ No newline at end of file
+</div>
index 507185c09e2f240996a8c9a223cc57cc22b60f1d..660535eccf061a784e1160710e59a638c6b45e58 100644 (file)
@@ -6,35 +6,37 @@
   <%= link_to 'Back to Users', user_manager_index_path, class: "button" %>
 </div>
 
+<%= render partial: "layouts/alert" %>
+
 <div class="post">
        <div class="container">
                <dl>
                <dt>Email:</dt>
                <dd><%= @user.email %></dd>
-               
+
                <dt>Name:</dt>
                <dd><%= @user.full_name %></dd>
-               
+
                <dt>Admin:</dt>
                <dd><%= @user.admin? ? 'Yes' : 'No' %></dd>
-               
+
                <dt>2FA Enabled:</dt>
                <dd><%= @user.otp_required_for_login? ? 'Yes' : 'No' %></dd>
-               
+
                <dt>Subscription Status:</dt>
                <dd><%= @user.subscription_status %></dd>
-               
+
                <dt>Mailing List Status:</dt>
                <dd><%= @user.buttondown_status %></dd>
-               
+
                <dt>Support Type:</dt>
                <dd><%= @user.support_type %></dd>
-               
+
                <dt>Last Payment Date:</dt>
                <dd><%= @user.last_payment_at&.to_s || 'N/A' %></dd>
-               
+
                <dt>Last Payment Amount:</dt>
                <dd><%= number_to_currency(@user.payment_amount) if @user.payment_amount.present? %></dd>
                </dl>
        </div>
-</div>
\ No newline at end of file
+</div>