From 3ce3481a1a0ed1d26ef29fc1887c7eed595d6327 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Mon, 7 Jul 2025 19:59:04 -0700 Subject: [PATCH] wip dashboard redesign (again lol) --- app/controllers/application_controller.rb | 29 + .../components/_active_discussions.html.erb | 48 +- .../main/components/_content_library.html.erb | 198 ++++++ .../components/_create_new_page_list.html.erb | 161 +---- .../components/_quote_of_the_day.html.erb | 55 ++ .../_recently_edited_pages.html.erb | 192 +---- .../_serendipitous_question.html.erb | 65 +- app/views/main/components/_whats_new.html.erb | 55 ++ app/views/main/dashboard.html.erb | 657 +++++++----------- 9 files changed, 737 insertions(+), 723 deletions(-) create mode 100644 app/views/main/components/_content_library.html.erb create mode 100644 app/views/main/components/_quote_of_the_day.html.erb create mode 100644 app/views/main/components/_whats_new.html.erb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 795f5346..c52c5a26 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -79,6 +79,7 @@ class ApplicationController < ActionController::Base cache_current_user_content cache_notifications cache_recently_edited_pages + cache_most_edited_pages end def cache_activated_content_types @@ -157,6 +158,34 @@ class ApplicationController < ActionController::Base end end + def cache_most_edited_pages(amount=50) + cache_current_user_content + + @most_edited_pages ||= if user_signed_in? + # Get all user's content + all_content = @current_user_content.values.flatten + + # Count edits for each content page using ContentChangeEvent + content_with_edit_counts = all_content.map do |content_page| + edit_count = ContentChangeEvent.where( + content_type: content_page.page_type, + content_id: content_page.id, + user_id: current_user.id + ).count + + [content_page, edit_count] + end + + # Sort by edit count (descending) and take the top pages + # Keep both content page and edit count for the view + content_with_edit_counts + .sort_by { |content_page, edit_count| -edit_count } + .first(amount) + else + [] + end + end + def cache_forums_unread_counts @unread_threads ||= if user_signed_in? Thredded::Topic.unread_followed_by(current_user).count diff --git a/app/views/main/components/_active_discussions.html.erb b/app/views/main/components/_active_discussions.html.erb index 432303b3..b6eb817f 100644 --- a/app/views/main/components/_active_discussions.html.erb +++ b/app/views/main/components/_active_discussions.html.erb @@ -1,19 +1,37 @@ - + + +
+ <%= link_to thredded_path, class: "block text-center text-sm text-orange-600 hover:text-orange-700 font-medium" do %> + Join the discussion → + <% end %> +
+ diff --git a/app/views/main/components/_content_library.html.erb b/app/views/main/components/_content_library.html.erb new file mode 100644 index 00000000..f47f1523 --- /dev/null +++ b/app/views/main/components/_content_library.html.erb @@ -0,0 +1,198 @@ +
+
+
+

+ library_books + Content Library +

+ + +
+ + + + +
+
+
+ +
+ + +
+
+ <% @current_user_content.except('Universe').values.flatten.sort_by(&:updated_at).reverse.first(15).each do |content_page| %> + <%= link_to send("edit_#{content_page.page_type.downcase}_path", content_page.id), class: 'block' do %> +
+
+ <% if content_page.random_image_including_private.present? %> + <%= image_tag content_page.random_image_including_private, class: 'w-full h-full object-cover' %> + <% else %> +
+ <%= content_page.icon %> +
+ <% end %> + +
+ +
+ <%= content_page.icon %> + <%= content_page.page_type %> +
+ +

+ <%= content_page.name %> +

+
+ +
+
+ <% if content_page.cached_word_count.present? %> + + description + <%= number_with_delimiter content_page.cached_word_count %> words + + <% end %> +
+ + schedule + edited <%= time_ago_in_words content_page.updated_at %> ago + +
+
+ <% end %> + <% end %> +
+
+ + + + + + + + + + +
+
\ No newline at end of file diff --git a/app/views/main/components/_create_new_page_list.html.erb b/app/views/main/components/_create_new_page_list.html.erb index b467d60e..eb677735 100644 --- a/app/views/main/components/_create_new_page_list.html.erb +++ b/app/views/main/components/_create_new_page_list.html.erb @@ -1,149 +1,30 @@ - + - - - diff --git a/app/views/main/components/_quote_of_the_day.html.erb b/app/views/main/components/_quote_of_the_day.html.erb new file mode 100644 index 00000000..b516c74a --- /dev/null +++ b/app/views/main/components/_quote_of_the_day.html.erb @@ -0,0 +1,55 @@ +
+
+
+ <% + quotes = [ + { text: "The secret to getting ahead is getting started.", author: "Mark Twain" }, + { text: "A story is a character who wants something and overcomes conflict to get it.", author: "Donald Maass" }, + { text: "You can't use up creativity. The more you use, the more you have.", author: "Maya Angelou" }, + { text: "The first draft of anything is shit.", author: "Ernest Hemingway" }, + { text: "Write what you need to know, not what you already know.", author: "Donald Barthelme" }, + { text: "I can shake off everything as I write; my sorrows disappear, my courage is reborn.", author: "Anne Frank" }, + { text: "The role of a writer is not to say what we all can say, but what we are unable to say.", author: "Anaïs Nin" }, + { text: "We write to taste life twice, in the moment and in retrospect.", author: "Anaïs Nin" }, + { text: "There is nothing to writing. All you do is sit down at a typewriter and bleed.", author: "Ernest Hemingway" }, + { text: "The scariest moment is always just before you start.", author: "Stephen King" }, + { text: "Don't tell me the moon is shining; show me the glint of light on broken glass.", author: "Anton Chekhov" }, + { text: "If you want to be a writer, you must do two things above all others: read a lot and write a lot.", author: "Stephen King" }, + { text: "The art of writing is the art of discovering what you believe.", author: "Gustave Flaubert" }, + { text: "You don't start out writing good stuff. You start out writing crap and thinking it's good stuff, and then gradually you get better at it.", author: "Octavia Butler" }, + { text: "A good story should make you laugh, and a moment later break your heart.", author: "Chuck Palahniuk" }, + { text: "Writing is an exploration. You start from nothing and learn as you go.", author: "E.L. Doctorow" }, + { text: "There is no greater agony than bearing an untold story inside you.", author: "Maya Angelou" }, + { text: "A writer is someone for whom writing is more difficult than it is for other people.", author: "Thomas Mann" }, + { text: "The only way to write a novel is to assume that you will never publish it.", author: "John Irving" }, + { text: "The best time for planning a book is while you're doing the dishes.", author: "Agatha Christie" }, + { text: "You can make anything by writing.", author: "C.S. Lewis" }, + { text: "Writing is the painting of the voice.", author: "Voltaire" }, + { text: "A writer is a world trapped in a person.", author: "Victor Hugo" }, + { text: "The writer's job is to tell the truth, even when it hurts.", author: "George Orwell" }, + { text: "The best stories are those that are true, even if they never happened.", author: "Unknown" }, + { text: "Writing is the only way I have to explain my own life to myself.", author: "Pat Conroy" }, + { text: "A writer is a person who can make a story out of anything.", author: "Neil Gaiman" }, + { text: "The only way to write is to write a lot.", author: "Ray Bradbury" }, + { text: "Writing is the only profession where no one considers you ridiculous if you earn no money.", author: "Jules Renard" }, + { text: "A writer is someone who has something to say and knows how to say it.", author: "William Zinsser" }, + { text: "The best way to predict the future is to invent it.", author: "Alan Kay" }, + { text: "Writing is a socially acceptable form of schizophrenia.", author: "E.L. Doctorow" }, + { text: "The only thing worse than starting something and failing is not starting something.", author: "Seth Godin" } + ] + + # Use day of year to ensure same quote per day + day_of_year = Time.current.yday + today_quote = quotes[day_of_year % quotes.length] + %> + +
+ "<%= today_quote[:text] %>" +
+ +
+ — <%= today_quote[:author] %> +
+
+
+
\ No newline at end of file diff --git a/app/views/main/components/_recently_edited_pages.html.erb b/app/views/main/components/_recently_edited_pages.html.erb index 02d41836..35309a9b 100644 --- a/app/views/main/components/_recently_edited_pages.html.erb +++ b/app/views/main/components/_recently_edited_pages.html.erb @@ -1,169 +1,51 @@ -
- <% @recently_edited_pages.first(9).each do |page| %> +
+ <% @recently_edited_pages.first(6).each do |page| %> <%# Timelines and Documents use edit_polymorphic_path, while ContentPages uses edit_path -- gross %> <%= link_to page.try(:view_path) || edit_polymorphic_path(page), class: 'block w-full group' do %> -
- -
- <%= image_tag page.random_image_including_private, class: 'absolute inset-0 w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' %> - - -
- - -
-
- <%= page.icon %> - <%= page.page_type %> +
+
+ +
+
+ <%= page.icon %>
- - -
-

+ + +
+

<%= page.name %> -

-
-

- - -
- -
-
+ +
+ + schedule + edited <%= time_ago_in_words page.updated_at %> ago + <% if page.cached_word_count.present? %> -
- description - - <%= number_with_delimiter page.cached_word_count %> - <%= 'word'.pluralize(page.cached_word_count) %> - -
+ + description + <%= number_with_delimiter page.cached_word_count %> words + + <% end %> + <% if page.respond_to?(:favorite?) && page.favorite? %> + star <% end %>
-
- schedule - edited <%= time_ago_in_words page.updated_at %> ago -
+
+ + +
+ arrow_forward
<% end %> <% end %> -
- - - - \ No newline at end of file + +
+ <%= link_to recent_content_path, class: "block text-center text-sm text-blue-600 hover:text-blue-700 font-medium" do %> + View all recent updates → + <% end %> +
+
diff --git a/app/views/main/components/_serendipitous_question.html.erb b/app/views/main/components/_serendipitous_question.html.erb index 0e588a61..1a9930e3 100644 --- a/app/views/main/components/_serendipitous_question.html.erb +++ b/app/views/main/components/_serendipitous_question.html.erb @@ -1,21 +1,54 @@ <% if @content %> -
-
- <%= image_tag @content.random_image_including_private(format: :original), class: 'w-full object-cover object-center max-h-48 rounded-t-md' %> -
-
-
- <%= - if @attribute_field_to_question - render partial: 'cards/serendipitous/tailwind_content_question', locals: { - content: @content, - field: @attribute_field_to_question, - expand_by_default: true, - include_quick_reference: false - } - end - %> +
+ +
+ <%= image_tag @content.random_image_including_private(format: :original), class: 'w-full h-full object-cover' %> +
+ + +
+
+ <%= @content.icon %> + <%= @content.page_type %> +
+ + +
+

+ <%= link_to @content.name, send("#{@content.page_type.downcase}_path", @content.id), class: "hover:text-blue-200 transition-colors" %> +

+

+ <% if @content.respond_to?(:universe) && @content.universe.present? %> + from <%= @content.universe.name %> + <% end %> +

+
+
+ + +
+ <% if @attribute_field_to_question %> + <%= render partial: 'cards/serendipitous/tailwind_content_question', locals: { + content: @content, + field: @attribute_field_to_question, + expand_by_default: true, + include_quick_reference: false + } %> + + +
+ <%= link_to send("edit_#{@content.page_type.downcase}_path", @content.id), class: "inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-lg text-white #{@content.color} hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all duration-200" do %> + edit + Work on this + <% end %> + + +
+ <% end %>
<% end %> \ No newline at end of file diff --git a/app/views/main/components/_whats_new.html.erb b/app/views/main/components/_whats_new.html.erb new file mode 100644 index 00000000..b49b5652 --- /dev/null +++ b/app/views/main/components/_whats_new.html.erb @@ -0,0 +1,55 @@ +
+
+

+ new_releases + What's New +

+
+
+
+
+ fiber_new + Latest Update +
+ +

Search & Discovery Improvements

+

+ We've enhanced the search experience with instant autocomplete and multi-word search capabilities. Find your content faster than ever! +

+ +
+ December 2024 + +
+
+ + +
+
+
+
+ Template editor consolidation +
+ Dec 7 +
+ +
+
+
+ Universe organization guide +
+ Dec 7 +
+ +
+
+
+ Dashboard redesign +
+ Dec 7 +
+
+
+
\ No newline at end of file diff --git a/app/views/main/dashboard.html.erb b/app/views/main/dashboard.html.erb index 86c27350..9ee3b114 100644 --- a/app/views/main/dashboard.html.erb +++ b/app/views/main/dashboard.html.erb @@ -1,302 +1,201 @@ -
-
-
- -
-
-
-
- -
- <%= link_to current_user, class: "group relative self-center sm:self-auto" do %> -
- <%= image_tag current_user.image_url, class: "h-16 w-16 sm:h-20 sm:w-20 rounded-full #{User.color} ring-4 ring-white shadow-lg group-hover:ring-blue-100 transition-all duration-200" %> -
-
- <% end %> - -
-
-

- Welcome back, <%= link_to current_user.display_name, current_user, class: "#{User.text_color} hover:opacity-80 transition-opacity" %> -

- <%= render partial: 'thredded/users/badge', locals: { user: current_user } %> -
-

- Ready to create something amazing today? -

- - -
-
- - -
- <%= link_to new_character_path do %> - - <% end %> - <% random_enabled_page_type = (current_user.createable_content_types - [Character]).sample %> - <%= link_to new_polymorphic_path(random_enabled_page_type) do %> - - <% end %> -
+ +
+ + +
+
+
+ + +
+ <%= link_to current_user, class: "group relative" do %> +
+ <%= image_tag current_user.image_url, class: "h-14 w-14 rounded-full #{User.color} ring-3 ring-white shadow-md group-hover:ring-blue-100 transition-all duration-200" %> +
+ <% end %> + +
+

+ Welcome back, <%= link_to current_user.display_name, current_user, class: "#{User.text_color} hover:opacity-80 transition-opacity" %> +

+ + + <%= render partial: 'main/components/quote_of_the_day', locals: { } %>
-
- - <%# render partial: 'main/components/activity_bar', locals: { } %> - -
- -
- -
- <% if @content %> -
-

- Expand - <% if @universe_scope.present? %> - <%= link_to @universe_scope.name, @universe_scope, class: Universe.text_color %> - <% else %> - your worlds - <% end %> -

- <%= render partial: 'main/components/serendipitous_question', locals: { } %> -
- <% end %> - -
-

- Create a new page -

- <%= render partial: 'main/components/create_new_page_list', locals: { } %> -
-
+ + +
+ <%= link_to new_character_path, class: "inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-lg text-gray-700 bg-white hover:bg-gray-50 hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all duration-200" do %> + <%= Character.icon %> + Create Character + <% end %> - -
- <% if @most_recent_threads.any? %> -
-

- <%= link_to 'Active discussions', thredded_path %> -

- <%= render partial: 'main/components/active_discussions', locals: { discussions: @most_recent_threads } %> -
- <% end %> - - <% if @recently_edited_pages %> -
-

- <%= link_to 'Your recent updates', recent_content_path %> -

- <%= render partial: 'main/components/recently_edited_pages', locals: { } %> -
- <% end %> -
- - - <% if @current_user_content && @current_user_content.except('Universe').values.flatten.any? %> -
-

Your Content

-
- <% @current_user_content.except('Universe').values.flatten.sort_by { |p| p.name.downcase }.each do |content_page| %> - <%= link_to send("edit_#{content_page.page_type.downcase}_path", content_page.id), class: 'block w-full group' do %> -
- -
- <% if content_page.random_image_including_private.present? %> - <%= image_tag content_page.random_image_including_private, class: 'absolute inset-0 w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' %> - <% else %> - -
- <% end %> - - -
- - -
-
- <%= content_page.icon %> - <%= content_page.page_type %> -
-
- - -
-

- <%= content_page.name %> -

-
-
- - -
- -
-
- <% if content_page.cached_word_count.present? %> -
- description - - <%= number_with_delimiter content_page.cached_word_count %> - <%= 'word'.pluralize(content_page.cached_word_count) %> - -
- <% end %> -
-
- schedule - edited <%= time_ago_in_words content_page.updated_at %> ago -
-
-
-
- <% end %> - <% end %> -
-
+ <% random_enabled_page_type = (current_user.createable_content_types - [Character]).sample %> + <%= link_to new_polymorphic_path(random_enabled_page_type), class: "inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-lg text-white #{random_enabled_page_type.color} hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all duration-200" do %> + <%= random_enabled_page_type.icon %> + Create <%= random_enabled_page_type.name %> <% end %>
-
- +
+ +
+ <%= render partial: 'main/components/create_new_page_list', locals: { } %> +
+ + + <% if @content %> +
+
+ + +
+ + +
+ <%= render partial: 'main/components/serendipitous_question', locals: { } %> +
+ + + <% if @recently_edited_pages %> +
+
+

+ history + Recently Edited +

+ <%= link_to recent_content_path, class: "text-xs text-blue-600 hover:text-blue-700 font-medium" do %> + View all → + <% end %> +
+ + +
+
+ <%= render partial: 'main/components/recently_edited_pages', locals: { } %> +
+
+
+ <% end %> + +
+
+
+ <% end %> + + <% if @most_edited_pages && @most_edited_pages.any? %> +
+
+
+

+ library_books + Most-Edited Pages +

+ <%= link_to recent_content_path, class: "text-sm text-blue-600 hover:text-blue-700 font-medium" do %> + View more → + <% end %> +
+ + +
+
+ <% @most_edited_pages.first(20).each do |content_page, edit_count| %> + <%= link_to send("edit_#{content_page.page_type.downcase}_path", content_page.id), class: 'block flex-shrink-0' do %> +
+
+ <% if content_page.random_image_including_private.present? %> + <%= image_tag content_page.random_image_including_private, class: 'w-full h-full object-cover' %> + <% else %> +
+ <%= content_page.icon %> +
+ <% end %> + +
+ +
+ <%= content_page.icon %> + <%= content_page.page_type %> +
+ + <% if content_page.respond_to?(:favorite?) && content_page.favorite? %> +
+ star +
+ <% end %> + +

+ <%= content_page.name %> +

+
+ +
+
+ + edit + <%= number_with_delimiter edit_count %> <%= 'edit'.pluralize(edit_count) %> + + + <% if content_page.cached_word_count.present? %> + + description + <%= number_with_delimiter content_page.cached_word_count %> <%= 'word'.pluralize(content_page.cached_word_count) %> + + <% end %> +
+
+
+ <% end %> + <% end %> +
+
+
+
+ <% end %> + + +
+ + +
+ + + <%= render partial: 'main/components/whats_new', locals: { } %> + + + <% if @most_recent_threads.any? %> +
+
+

+ forum + <%= link_to 'Forum Activity', thredded_path, class: "hover:text-orange-600 transition-colors" %> +

+
+
+
+ <%= render partial: 'main/components/active_discussions', locals: { discussions: @most_recent_threads } %> +
+
+
+ <% end %> + +
+ +
+
- - <%= render partial: 'javascripts/content_linking' %>