diff --git a/app/assets/javascripts/content_types.js b/app/assets/javascripts/content_types.js new file mode 100644 index 000000000..83fd6f2bc --- /dev/null +++ b/app/assets/javascripts/content_types.js @@ -0,0 +1,24 @@ +$(document).ready(function() { + $('.js-enable-content-type').click(function () { + var content_type = $(this).data('content-type'); + var related_card = $(this).children('.card').first(); + var is_currently_active = related_card.hasClass('active'); + var ie_badge = $(this).find('.enabled-badge'); + + $.post('/customization/toggle_content_type', { + content_type: content_type, + active: is_currently_active ? 'off' : 'on' + }); + + if (is_currently_active) { + related_card.removeClass('active'); + ie_badge.attr('data-badge-caption', 'hidden'); + } else { + related_card.addClass('active'); + ie_badge.attr('data-badge-caption', 'active'); + } + + // Return false so we don't jump to the top of the page on link click + return false; + }); +}); diff --git a/app/assets/javascripts/navbar.js b/app/assets/javascripts/navbar.js new file mode 100644 index 000000000..d773dd76c --- /dev/null +++ b/app/assets/javascripts/navbar.js @@ -0,0 +1,5 @@ +// $(document).ready(function () { +// $('.tab-link').click(function() { +// document.location = $(this).attr('href'); +// }); +// }); diff --git a/app/assets/javascripts/navbar.js.coffee b/app/assets/javascripts/navbar.js.coffee deleted file mode 100644 index 1c2ac0229..000000000 --- a/app/assets/javascripts/navbar.js.coffee +++ /dev/null @@ -1 +0,0 @@ -$( -> $(".button-collapse").sidenav() ) diff --git a/app/assets/stylesheets/autosave.scss b/app/assets/stylesheets/autosave.scss new file mode 100644 index 000000000..9d855135d --- /dev/null +++ b/app/assets/stylesheets/autosave.scss @@ -0,0 +1,17 @@ +.autosave-bar { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + + margin: 0; + padding: 4px 0; + + text-align: center; + background: white; + border-top: 2px solid lightgrey; + + i { + font-size: 15px; + } +} diff --git a/app/assets/stylesheets/btn-group.scss b/app/assets/stylesheets/btn-group.scss new file mode 100644 index 000000000..3d4d159b8 --- /dev/null +++ b/app/assets/stylesheets/btn-group.scss @@ -0,0 +1,44 @@ +.btn-group { + position: relative; + display: -ms-inline-flexbox; + display: inline-flex; +} + +.btn-group.card { + margin: 0; +} + +.btn-group>.btn:first-child:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group>.btn:not(:first-child):not(:last-child) { + border-radius: 0; + border-left: 1px solid lightgrey; +} + +.btn-group>.btn:last-child:not(:first-child), +.btn-group>.dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: 1px solid lightgrey; +} + +.btn-group>.btn-inactive { + background-color: #607d8b; +} + +.btn-group>.btn { + -webkit-box-shadow: 0 0px 0px 0 rgba(0, 0, 0, 0), 0 0px 0px 0px rgba(0, 0, 0, 0), 0 0px 0px 0 rgba(0, 0, 0, 0); + box-shadow: 0 0px 0px 0 rgba(0, 0, 0, 0), 0 0px 0px 0px rgba(0, 0, 0, 0), 0 0px 0px 0 rgba(0, 0, 0, 0); +} + +.btn-group>.btn-inactive:hover { + background-color: #728F9D; +} + +.btn-group>.btn:hover { + -webkit-box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2); +} diff --git a/app/assets/stylesheets/content.css.scss b/app/assets/stylesheets/content.css.scss index eae8fe329..94a4efa6c 100644 --- a/app/assets/stylesheets/content.css.scss +++ b/app/assets/stylesheets/content.css.scss @@ -14,15 +14,13 @@ p.long-form { margin-bottom: 16px; } -.card-action { - .green-text, .red-text { - i { - font-size: 90%; - } +.card-action.nice-icon-links { + i { + font-size: 90%; + } - a { - color: grey; - } + a { + color: grey; } } @@ -127,3 +125,10 @@ p.long-form { margin-bottom: 30px; } + +.parallax-header { + img { + -webkit-filter: blur(3px); /* Safari 6.0 - 9.0 */ + filter: blur(3px); + } +} diff --git a/app/assets/stylesheets/content_types.scss b/app/assets/stylesheets/content_types.scss new file mode 100644 index 000000000..a5460d313 --- /dev/null +++ b/app/assets/stylesheets/content_types.scss @@ -0,0 +1,27 @@ +.js-enable-content-type .card:not(.active) { + -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */ + filter: grayscale(100%); + + .card-image > img { + -webkit-filter: blur(2px); /* Safari 6.0 - 9.0 */ + filter: blur(2px); + } +} + +.js-enable-content-type .card:not(.active):hover { + -webkit-filter: grayscale(75%); /* Safari 6.0 - 9.0 */ + filter: grayscale(75%); + + .card-image > img { + -webkit-filter: blur(0px); /* Safari 6.0 - 9.0 */ + filter: blur(0px); + } +} + +.js-enable-content-type .enabled-badge { + float: right; + position: relative; + top: -51px; + right: 7px; + z-index: 3; +} diff --git a/app/assets/stylesheets/dashboard.css.scss b/app/assets/stylesheets/dashboard.css.scss index 45e89e246..ca5fba42a 100644 --- a/app/assets/stylesheets/dashboard.css.scss +++ b/app/assets/stylesheets/dashboard.css.scss @@ -2,4 +2,4 @@ .card-image { max-height: 200px; } -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/editor.css.scss b/app/assets/stylesheets/editor.css.scss index 58eddcee1..ff1df25d5 100644 --- a/app/assets/stylesheets/editor.css.scss +++ b/app/assets/stylesheets/editor.css.scss @@ -2,13 +2,41 @@ min-height: 400px; border: 1px solid #dedede; padding: 5px 0; + margin-bottom: 600px; + + color: black; p { margin-top: 0; } + + /* PAGES */ + background: white; + padding: 30px; + border-bottom: 1px solid grey; } /* Materialize hacks */ b, strong { font-weight: bolder !important; } + +.document-name-bar { + .input-field.inline { + margin-bottom: 0; + } + + .row { + margin-bottom: 0; + } + + margin-bottom: 40px; +} + +.smart-sidebar { + opacity: 0.4; + + &:hover { + opacity: 1.0; + } +} diff --git a/app/assets/stylesheets/footer.css b/app/assets/stylesheets/footer.css index c94ab5177..f953277f2 100644 --- a/app/assets/stylesheets/footer.css +++ b/app/assets/stylesheets/footer.css @@ -7,3 +7,7 @@ body { main { flex: 1 0 auto; } + +.stealth-page-footer { + padding-bottom: 20px; +} diff --git a/app/assets/stylesheets/materialize-overrides.scss b/app/assets/stylesheets/materialize-overrides.scss index 51e747006..68591a935 100644 --- a/app/assets/stylesheets/materialize-overrides.scss +++ b/app/assets/stylesheets/materialize-overrides.scss @@ -6,13 +6,17 @@ @media only screen and (min-width: 1024px) { .fixed-card-content { - height: 8em; + height: 8em; } } @media only screen and (max-width: 1024px) { .fixed-card-content { - height: 10em; + height: 10em; } -} \ No newline at end of file +} + +body { + background: #f4f4f4; +} diff --git a/app/assets/stylesheets/navbar.css b/app/assets/stylesheets/navbar.css index 36fbfc047..c5a21229c 100644 --- a/app/assets/stylesheets/navbar.css +++ b/app/assets/stylesheets/navbar.css @@ -1,13 +1,34 @@ .dropdown-content { - min-width: 300px !important; + min-width: 400px !important; } -.navbar-fixed { - margin-bottom: 15px; - z-index: 1000 !important; +@media only screen and (min-width: 993px) { + body.has-fixed-sidenav { + padding-left: 300px !important; + } + + nav.navbar.logged-in { + width: calc(100% - 300px); + } +} + +@media only screen and (max-width: 993px) { + body.has-fixed-sidenav { + padding-left: 0 !important; + } +} + +@media only screen and (min-width: 601px) { + nav, nav .nav-wrapper i, nav a.sidenav-trigger, nav a.sidenav-trigger i { + height: 64px; + line-height: 64px; + } } -.universe-filter-active { - background: purple; - height: 100%; +nav.navbar { + z-index: 10; + transition: box-shadow .3s, background-color .3s; + padding: 0 20px; + background-color: #fff; + color: rgba(0,0,0,0.87); } diff --git a/app/assets/stylesheets/sidenav.css.scss b/app/assets/stylesheets/sidenav.css.scss index bcad62d25..cff23eaf5 100644 --- a/app/assets/stylesheets/sidenav.css.scss +++ b/app/assets/stylesheets/sidenav.css.scss @@ -1,14 +1,43 @@ .sidenav { - padding-top: 64px; + li { + display: block; + } + + .logo-container { + padding: 0 16px; + height: 64px; + line-height: 64px; + font-size: 24px; + border-bottom: 1px solid rgba(0,0,0,0.2); + box-sizing: content-box; + + i.material-icons.right { + position: relative; + top: 8px; + left: 26px; + } + } - .header { - background: #10B6FF; - color: white; - margin: 0; - text-align: center; + .collapsible .collapsible-header { + text-transform: uppercase; + height: 64px; + line-height: 64px; + + .material-icons.left { + margin-top: 8px; + } + } + + .collapsible .collapsible-header .chevron { + float: right; + height: 24px; + width: 24px; + line-height: 24px; + margin: 20px 0 0 0; + transition: transform .2s; + } - font-size: 12px; - height: 20px; - line-height: 20px; + .collapsible>.active .collapsible-header .chevron { + transform: rotate(-90deg); } } diff --git a/app/assets/stylesheets/thredded-overrides.scss b/app/assets/stylesheets/thredded-overrides.scss index 8d0099ed5..1ed5bc352 100644 --- a/app/assets/stylesheets/thredded-overrides.scss +++ b/app/assets/stylesheets/thredded-overrides.scss @@ -1,5 +1,81 @@ @import "thredded"; +#thredded--container { + #q /* search input */ { + height: 37px; + padding-left: 16px; + } + + .thredded--user-navigation { + height: 64px; + } + + .thredded--currently-online { + right: 100px; + } + + .thredded--new-topic-form { + background: white; + padding: 10px; + padding-bottom: 0; + border: 1px solid lightgrey; + + margin-bottom: 20px; + } + + .thredded--topics--topic { + background: white; + padding: 4px 26px; + border: 1px solid lightgrey; + + margin-bottom: 0.7rem; + } + + .thredded--topics--posts-count { + left: -1rem; + top: 2px; + } + + .thredded--topics--follow-icon { + right: 0.2rem; + top: 6px; + } + + .thredded--pagination { + background: white; + padding: 0 0 10px 0; + } + + .thredded--topic .thredded--post { + background: white; + padding: 10px; + + margin-bottom: 20px; + border-bottom: 1px solid lightgrey; + } + + @media (min-width: 47.12501rem) { + .thredded--post--avatar { + top: 0; + } + } + + .thredded--messageboard { + background: white; + border-bottom: 1px solid lightgrey; + margin: 2px; + } +} + +.thredded--main-header { + nav { + background: white; + padding: 0 10px; + + margin-bottom: 100px; + } +} + .thredded--main-container { // The padding and max-width are handled by the app's container. min-width: 80%; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7faf7a369..1a31a429b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -48,7 +48,9 @@ def cache_most_used_page_information current_user.user_content_type_activators.pluck(:content_type) ) - @current_user_content = current_user.content(content_types: @activated_content_types) + # We always want to cache Universes, even if they aren't explicitly turned on. + @current_user_content = current_user.content(content_types: @activated_content_types + ['Universe']) + @current_user_content['Document'] = current_user.documents end def cache_forums_unread_counts diff --git a/app/controllers/content_controller.rb b/app/controllers/content_controller.rb index 83d1659f6..fe1c409b6 100644 --- a/app/controllers/content_controller.rb +++ b/app/controllers/content_controller.rb @@ -8,6 +8,13 @@ class ContentController < ApplicationController before_action :populate_linkable_content_for_each_content_type, only: [:new, :edit] + before_action :set_attributes_content_type, only: [:attributes] + + before_action :set_navbar_color + before_action :set_general_navbar_actions, except: [:deleted, :show, :changelog] + before_action :set_specific_navbar_actions, only: [:show, :changelog] + before_action :set_sidenav_expansion + def index @content_type_class = content_type_from_controller(self.class) pluralized_content_name = @content_type_class.name.downcase.pluralize @@ -44,6 +51,18 @@ def show return redirect_to(root_path, notice: "You don't have permission to view that content.") if @content.nil? @serialized_content = ContentSerializer.new(@content) + if user_signed_in? + @navbar_actions << { + label: @serialized_content.name, + href: main_app.polymorphic_path(@content) + } + + @navbar_actions << { + label: 'Changelog', + href: send("changelog_#{content_type.name.downcase}_path", @content) + } + end + return redirect_to(root_path) if @content.user.nil? # deleted user's content return if ENV.key?('CONTENT_BLACKLIST') && ENV['CONTENT_BLACKLIST'].split(',').include?(@content.user.try(:email)) @@ -81,7 +100,7 @@ def new # todo this is a good spot to audit to disable and see if create permissions are ok also unless (current_user || User.new).can_create?(content_type_from_controller(self.class)) - return redirect_back(fallback_location: root_path) + return redirect_to(subscription_path, notice: "#{@content.class.name.pluralize} require a Premium subscription to create.") end respond_to do |format| @@ -143,7 +162,7 @@ def create upload_files params['image_uploads'], content_type.name, @content.id end - successful_response(content_creation_redirect_url, t(:create_success, model_name: humanized_model_name)) + successful_response(content_creation_redirect_url, t(:create_success, model_name: @content.try(:name).presence || humanized_model_name)) else failed_response('new', :unprocessable_entity, "Unable to save page. Error code: " + @content.errors.map(&:messages).to_sentence) end @@ -189,12 +208,32 @@ def update end if update_success - successful_response(@content, t(:update_success, model_name: humanized_model_name)) + successful_response(@content, t(:update_success, model_name: @content.try(:name).presence || humanized_model_name)) else failed_response('edit', :unprocessable_entity, "Unable to save page. Error code: " + @content.errors.map(&:messages).to_sentence) end end + def changelog + content_type = content_type_from_controller(self.class) + return redirect_to root_path unless valid_content_types.map(&:name).include?(content_type.name) + @content = content_type.find_by(id: params[:id]) + return redirect_to(root_path, notice: "You don't have permission to view that content.") if @content.nil? + @serialized_content = ContentSerializer.new(@content) + + if user_signed_in? + @navbar_actions << { + label: @serialized_content.name, + href: main_app.polymorphic_path(@content) + } + + @navbar_actions << { + label: 'Changelog', + href: send("changelog_#{content_type.name.downcase}_path", @content) + } + end + end + def upload_files image_uploads_list, content_type, content_id image_uploads_list.each do |image_data| image_size_kb = File.size(image_data.tempfile.path) / 1000.0 @@ -237,9 +276,10 @@ def destroy 'content_type': content_type.name }) if Rails.env.production? + cached_page_name = @content.try(:name) @content.destroy - successful_response(content_deletion_redirect_url, t(:delete_success, model_name: humanized_model_name)) + successful_response(content_deletion_redirect_url, t(:delete_success, model_name: cached_page_name.presence || humanized_model_name)) end # List all recently-deleted content @@ -249,15 +289,12 @@ def deleted @content_pages[content_type] = content_type.constantize.with_deleted.where('deleted_at > ?', 24.hours.ago).where(user_id: current_user.id) end @content_pages["Document"] = current_user.documents.with_deleted.where('deleted_at > ?', 24.hours.ago) + + # Override controller + @sidenav_expansion = 'my account' end def attributes - @content_type = params[:content_type] - # todo make this a before_action load_content_type - unless valid_content_types.map { |c| c.name.downcase }.include?(@content_type) - raise "Invalid content type on attributes customization page: #{@content_type}" - end - @content_type_class = @content_type.titleize.constantize end private @@ -368,4 +405,73 @@ def failed_response(action, status, notice=nil) def humanized_model_name content_type_from_controller(self.class).model_name.human end + + def set_attributes_content_type + @content_type = params[:content_type] + # todo make this a before_action load_content_type + unless valid_content_types.map { |c| c.name.downcase }.include?(@content_type) + raise "Invalid content type on attributes customization page: #{@content_type}" + end + @content_type_class = @content_type.titleize.constantize + end + + def set_navbar_color + content_type = @content_type_class || content_type_from_controller(self.class) + @navbar_color = content_type.try(:hex_color) || '#2196F3' + end + + # For index, new, edit + def set_general_navbar_actions + content_type = @content_type_class || content_type_from_controller(self.class) + @navbar_actions = [] + + if @current_user_content + @navbar_actions << { + label: "Your #{view_context.pluralize @current_user_content.fetch(content_type.name, []).count, content_type.name.downcase}", + href: main_app.polymorphic_path(content_type) + } + end + + @navbar_actions << { + label: "New #{content_type.name.downcase}", + href: main_app.new_polymorphic_path(content_type) + } + + discussions_link = ForumsLinkbuilderService.worldbuilding_url(content_type) + if discussions_link.present? + @navbar_actions << { + label: 'Discussions', + href: discussions_link + } + end + + @navbar_actions << { + label: 'Customize template', + href: main_app.attribute_customization_path(content_type.name.downcase) + } + end + + # For showing a specific piece of content + def set_specific_navbar_actions + content_type = @content_type_class || content_type_from_controller(self.class) + @navbar_actions = [] + + if user_signed_in? + if @current_user_content + @navbar_actions << { + label: "Your #{view_context.pluralize @current_user_content.fetch(content_type.name, []).count, content_type.name.downcase}", + href: main_app.polymorphic_path(content_type) + } + end + # + # @navbar_actions << { + # label: "New #{content_type.name.downcase}", + # href: main_app.new_polymorphic_path(content_type) + # } + end + end + + def set_sidenav_expansion + @sidenav_expansion = 'worldbuilding' + end end diff --git a/app/controllers/customization_controller.rb b/app/controllers/customization_controller.rb index 4ff12effa..9eb40a121 100644 --- a/app/controllers/customization_controller.rb +++ b/app/controllers/customization_controller.rb @@ -7,6 +7,7 @@ def content_types @all_content_types = Rails.application.config.content_types[:all] @premium_content_types = Rails.application.config.content_types[:premium] @my_activators = current_user.user_content_type_activators.pluck(:content_type) + @sidenav_expansion = 'worldbuilding' end def toggle_content_type diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb index 5f0b71bf3..665fb7801 100644 --- a/app/controllers/documents_controller.rb +++ b/app/controllers/documents_controller.rb @@ -1,13 +1,26 @@ class DocumentsController < ApplicationController before_action :authenticate_user! + before_action :set_sidenav_expansion + before_action :set_navbar_color + before_action :set_navbar_actions, except: [:edit] + before_action :set_footer_visibility, only: [:edit] + def index @documents = current_user.documents.order('updated_at desc') end def show - document = Document.find_by(id: params[:id], user_id: current_user.id) - redirect_to edit_document_path(document) + @document = Document.find_by(id: params[:id], user_id: current_user.id) + + unless @document.present? || @document.viewable_by?(current_user || User.new) + redirect_to(root_path, notice: "That document either doesn't exist or you don't have permission to view it.") + end + + @navbar_actions.unshift({ + label: (@document.name || 'Untitled document'), + href: document_path(@document) + }) end def edit @@ -46,10 +59,39 @@ def destroy if current_user.can_delete?(document) document.destroy - redirect_back(fallback_location: documents_path, notice: "The document was successfully deleted.") + redirect_to(documents_path, notice: "The document was successfully deleted.") else - redirect_back(fallback_location: root_path, notice: "You don't have permission to do that!") + redirect_to(root_path, notice: "You don't have permission to do that!") + end + end + + def set_sidenav_expansion + @sidenav_expansion = 'writing' + end + + def set_navbar_color + content_type = content_type_from_controller(self.class) + @navbar_color = content_type.hex_color + end + + def set_navbar_actions + @navbar_actions = [] + + if @current_user_content['Document'].present? + @navbar_actions << { + label: "Your #{@current_user_content['Document'].count} Document#{'s' unless @navbar_actions == 1}", + href: documents_path + } end + + @navbar_actions << { + label: "New Document", + href: edit_document_path(:new) + } + end + + def set_footer_visibility + @show_footer = false end private diff --git a/app/controllers/export_controller.rb b/app/controllers/export_controller.rb index 82333a413..de3a3f171 100644 --- a/app/controllers/export_controller.rb +++ b/app/controllers/export_controller.rb @@ -3,6 +3,8 @@ class ExportController < ApplicationController before_action :whitelist_pluralized_model, only: [:csv] def index + @sidenav_expansion = 'my account' + Mixpanel::Tracker.new(Rails.application.config.mixpanel_token).track(current_user.id, 'viewed export page', { 'content count': current_user.content_count }) if Rails.env.production? @@ -27,13 +29,13 @@ def outline def notebook_json report_to_mixpanel 'json', 'notebook' - json_dump = current_user.content.map { |category, content| {"#{category}": fill_relations(category.constantize, content)} }.to_json + json_dump = current_user.content.except('Document').map { |category, content| {"#{category}": fill_relations(category.constantize, content)} }.to_json send_data json_dump, filename: "notebook-#{Date.today}.json" end def notebook_xml report_to_mixpanel 'xml', 'notebook' - xml_dump = current_user.content.map { |category, content| {"#{category}": fill_relations(category.constantize, content)}}.to_xml + xml_dump = current_user.content.except('Document').map { |category, content| {"#{category}": fill_relations(category.constantize, content)}}.to_xml send_data xml_dump, filename: "notebook-#{Date.today}.xml" end @@ -118,7 +120,7 @@ def fill_relations(ar_class, ar_relation) end def content_to_outline - content_types = current_user.content.keys + content_types = current_user.content.except('Document').keys text = "" content_types.each do |content_type| diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb index c5dab7d51..5413f4d26 100644 --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -28,9 +28,13 @@ def dashboard def prompts return redirect_to(new_user_session_path) unless user_signed_in? + @sidenav_expansion = 'writing' + @navbar_color = '#FF9800' + set_random_content # for question end + # deprecated path just kept around for bookmarks for a while def notes return redirect_to(new_user_session_path) unless user_signed_in? redirect_to edit_document_path(current_user.documents.first) @@ -68,6 +72,7 @@ def for_roleplayers def for_designers end + # deprecated path todo cleanup def for_friends @subscriber_count = User.where(selected_billing_plan_id: [3, 4]).count @drawing_date = 'June 15, 2017 12:00pm'.to_date @@ -81,6 +86,10 @@ def for_friends def feature_voting end + def privacyinfo + @sidenav_expansion = 'help' + end + private def set_random_content @@ -90,18 +99,23 @@ def set_random_content # when we want to enable prompts for contributing universes we can remove the user: # selector here, but we will need to verify the user has permission to see the universe # when we do that, or else prompts could open leak - @content = content_type.constantize.where(user: current_user, id: @universe_scope.id).sample + @content = content_type.constantize.where(user: current_user, id: @universe_scope.id).includes(:user) else - @content = content_type.constantize.where(user: current_user).sample + @content = content_type.constantize.where(user: current_user).includes(:user) end else if @universe_scope.present? - @content = content_type.constantize.where(user: current_user, universe: @universe_scope).sample + @content = content_type.constantize.where(user: current_user, universe: @universe_scope).includes(:user) else - @content = content_type.constantize.where(user: current_user).sample + @content = content_type.constantize.where(user: current_user).includes(:user) end end + unless @content.klass.name == Universe.name + @content = @content.includes(:universe) + end + + @content = @content.sample return if @content.present? end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 9465625c9..7051c3a79 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -1,6 +1,9 @@ class RegistrationsController < Devise::RegistrationsController after_action :add_account, only: [:create] + before_action :set_navbar_actions, only: [:edit] + before_action :set_navbar_color, only: [:edit] + def new super if params[:referral] @@ -8,6 +11,10 @@ def new end end + def edit + @sidenav_expansion = 'my account' + end + private def sign_up_params @@ -15,13 +22,24 @@ def sign_up_params end def account_update_params - params.require(:user).permit(:name, :email, :username, :password, :password_confirmation, :email_updates, :fluid_preference) + params.require(:user).permit( + :name, :email, :username, :password, :password_confirmation, :email_updates, :fluid_preference, + :bio, :favorite_genre, :favorite_author, :interests, :age, :location, :gender + ) end def update_resource(resource, params) resource.update_without_password(params) end + def set_navbar_color + @navbar_color = '#000000' + end + + def set_navbar_actions + @navbar_actions = [] + end + protected def add_account diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index da35d7efd..94379ecf1 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,6 +4,8 @@ def index end def show + @sidenav_expansion = 'my account' + @user = User.find_by(id: params[:id]) return redirect_to(root_path, notice: 'That user does not exist.') if @user.nil? diff --git a/app/models/concerns/has_content.rb b/app/models/concerns/has_content.rb index 3aa8178b8..ff3991256 100644 --- a/app/models/concerns/has_content.rb +++ b/app/models/concerns/has_content.rb @@ -23,10 +23,12 @@ def content( content_types: Rails.application.config.content_types[:all].map(&:name), page_scoping: { user_id: self.id } ) + return {} if content_types.empty? + polymorphic_content_fields = [:id, :name, :page_type, :user_id, :created_at, :updated_at, :deleted_at, :privacy] where_conditions = page_scoping.map { |key, value| "#{key} = #{value}" }.join(' AND ') + ' AND deleted_at IS NULL' - sql = content_types.map do |page_type| + sql = content_types.uniq.map do |page_type| "SELECT #{polymorphic_content_fields.join(',')} FROM #{page_type.downcase.pluralize} WHERE #{where_conditions}" end.join(' UNION ALL ') + ' ORDER BY page_type, id' @@ -51,7 +53,7 @@ def content_list( polymorphic_content_fields = [:id, :name, :page_type, :user_id, :created_at, :updated_at, :deleted_at, :privacy] where_conditions = page_scoping.map { |key, value| "#{key} = #{value}" }.join(' AND ') + ' AND deleted_at IS NULL' - sql = content_types.map do |page_type| + sql = content_types.uniq.map do |page_type| "SELECT #{polymorphic_content_fields.join(',')} FROM #{page_type.downcase.pluralize} WHERE #{where_conditions}" end.join(' UNION ALL ') diff --git a/app/models/content_types/building.rb b/app/models/content_types/building.rb index d1d184c32..1fcebd18b 100644 --- a/app/models/content_types/building.rb +++ b/app/models/content_types/building.rb @@ -21,6 +21,10 @@ def self.color 'blue-grey' end + def self.hex_color + '#607D8B' + end + def self.icon 'business' end diff --git a/app/models/content_types/character.rb b/app/models/content_types/character.rb index b5ffcee8f..2b52df8b0 100644 --- a/app/models/content_types/character.rb +++ b/app/models/content_types/character.rb @@ -57,6 +57,10 @@ def self.color 'red' end + def self.hex_color + '#F44336' + end + def self.icon 'group' end diff --git a/app/models/content_types/condition.rb b/app/models/content_types/condition.rb index 08f464530..dd411ca87 100644 --- a/app/models/content_types/condition.rb +++ b/app/models/content_types/condition.rb @@ -21,6 +21,10 @@ def self.color 'text-darken-1 lime' end + def self.hex_color + '#CDDC39' + end + def self.icon 'bubble_chart' end diff --git a/app/models/content_types/country.rb b/app/models/content_types/country.rb index f43bd5047..e7926c344 100644 --- a/app/models/content_types/country.rb +++ b/app/models/content_types/country.rb @@ -40,6 +40,10 @@ def self.color 'lighten-2 text-lighten-2 brown' end + def self.hex_color + '#A1887F' + end + def self.icon 'explore' end diff --git a/app/models/content_types/creature.rb b/app/models/content_types/creature.rb index 9964eeb8a..9c4fede3e 100644 --- a/app/models/content_types/creature.rb +++ b/app/models/content_types/creature.rb @@ -41,6 +41,10 @@ def self.color 'brown' end + def self.hex_color + '#795548' + end + def self.icon 'pets' end diff --git a/app/models/content_types/deity.rb b/app/models/content_types/deity.rb index b046acceb..2080421a1 100644 --- a/app/models/content_types/deity.rb +++ b/app/models/content_types/deity.rb @@ -41,6 +41,10 @@ def self.color 'text-lighten-4 blue' end + def self.hex_color + '#BBDEFB' + end + def self.icon 'ac_unit' end diff --git a/app/models/content_types/flora.rb b/app/models/content_types/flora.rb index 8b639d6f7..f5818e401 100644 --- a/app/models/content_types/flora.rb +++ b/app/models/content_types/flora.rb @@ -36,6 +36,10 @@ def self.color 'text-lighten-3 lighten-3 teal' end + def self.hex_color + '#80CBC4' + end + def self.icon 'local_florist' end diff --git a/app/models/content_types/government.rb b/app/models/content_types/government.rb index 00bc36aaa..2675e2d1d 100644 --- a/app/models/content_types/government.rb +++ b/app/models/content_types/government.rb @@ -31,6 +31,10 @@ def self.color 'darken-2 green' end + def self.hex_color + '#388E3C' + end + def self.icon 'account_balance' end diff --git a/app/models/content_types/group.rb b/app/models/content_types/group.rb index 46dedefac..40a106c7f 100644 --- a/app/models/content_types/group.rb +++ b/app/models/content_types/group.rb @@ -44,6 +44,10 @@ def self.color 'cyan' end + def self.hex_color + '#00BCD4' + end + def self.icon 'wc' end diff --git a/app/models/content_types/item.rb b/app/models/content_types/item.rb index 502729f80..2f6390192 100644 --- a/app/models/content_types/item.rb +++ b/app/models/content_types/item.rb @@ -40,6 +40,10 @@ def self.color 'amber' end + def self.hex_color + '#FFC107' + end + def self.icon 'beach_access' end diff --git a/app/models/content_types/job.rb b/app/models/content_types/job.rb index 8e8aef8ff..d072c945c 100644 --- a/app/models/content_types/job.rb +++ b/app/models/content_types/job.rb @@ -21,6 +21,10 @@ def self.color 'text-lighten-1 brown' end + def self.hex_color + '#795548' + end + def self.icon 'work' end diff --git a/app/models/content_types/landmark.rb b/app/models/content_types/landmark.rb index 4dc49a7c2..7cf7f5096 100644 --- a/app/models/content_types/landmark.rb +++ b/app/models/content_types/landmark.rb @@ -36,6 +36,10 @@ def self.color 'text-lighten-1 lighten-1 orange' end + def self.hex_color + '#FFA726' + end + def self.icon 'location_on' end diff --git a/app/models/content_types/language.rb b/app/models/content_types/language.rb index e38ae1897..63ed53e27 100644 --- a/app/models/content_types/language.rb +++ b/app/models/content_types/language.rb @@ -28,6 +28,10 @@ def self.color 'blue' end + def self.hex_color + '#2196F3' + end + def self.icon 'forum' end diff --git a/app/models/content_types/location.rb b/app/models/content_types/location.rb index dc5ba3b0f..632db5170 100644 --- a/app/models/content_types/location.rb +++ b/app/models/content_types/location.rb @@ -51,6 +51,10 @@ def self.color 'green' end + def self.hex_color + '#4CAF50' + end + def self.content_name 'location' end diff --git a/app/models/content_types/magic.rb b/app/models/content_types/magic.rb index 8b0a8a3ed..8b12cc779 100644 --- a/app/models/content_types/magic.rb +++ b/app/models/content_types/magic.rb @@ -30,6 +30,10 @@ def self.color 'orange' end + def self.hex_color + '#FF9800' + end + def self.icon 'flash_on' end diff --git a/app/models/content_types/planet.rb b/app/models/content_types/planet.rb index 2233deb3d..423092dc2 100644 --- a/app/models/content_types/planet.rb +++ b/app/models/content_types/planet.rb @@ -37,6 +37,10 @@ def self.color 'text-lighten-2 blue' end + def self.hex_color + '#64B5F6' + end + def self.icon 'public' end diff --git a/app/models/content_types/race.rb b/app/models/content_types/race.rb index 6573c8c7a..a19f6570b 100644 --- a/app/models/content_types/race.rb +++ b/app/models/content_types/race.rb @@ -36,6 +36,10 @@ def self.color 'light-green' end + def self.hex_color + '#8BC34A' + end + def self.icon 'face' end diff --git a/app/models/content_types/religion.rb b/app/models/content_types/religion.rb index 84dfcc825..b43b1a5a5 100644 --- a/app/models/content_types/religion.rb +++ b/app/models/content_types/religion.rb @@ -40,7 +40,11 @@ def description end def self.color - 'yellow' + 'indigo' + end + + def self.hex_color + '#3f51b5' end def self.icon diff --git a/app/models/content_types/scene.rb b/app/models/content_types/scene.rb index 8b77821ce..e732eb77e 100644 --- a/app/models/content_types/scene.rb +++ b/app/models/content_types/scene.rb @@ -36,6 +36,10 @@ def self.color 'grey' end + def self.hex_color + '#9E9E9E' + end + def self.icon 'local_movies' end diff --git a/app/models/content_types/technology.rb b/app/models/content_types/technology.rb index ba095ce60..0e9762d25 100644 --- a/app/models/content_types/technology.rb +++ b/app/models/content_types/technology.rb @@ -35,6 +35,10 @@ def self.color 'text-darken-2 red' end + def self.hex_color + '#D32F2F' + end + def self.icon 'router' end diff --git a/app/models/content_types/town.rb b/app/models/content_types/town.rb index 1a41a6ead..da18715b8 100644 --- a/app/models/content_types/town.rb +++ b/app/models/content_types/town.rb @@ -39,6 +39,10 @@ def self.color 'text-lighten-3 lighten-3 purple' end + def self.hex_color + '#CE93D8' + end + def self.icon 'location_city' end diff --git a/app/models/content_types/tradition.rb b/app/models/content_types/tradition.rb index 01e30edd9..031e77f61 100644 --- a/app/models/content_types/tradition.rb +++ b/app/models/content_types/tradition.rb @@ -21,6 +21,10 @@ def self.color 'text-lighten-3 lighten-3 red' end + def self.hex_color + '#EF9A9A' + end + def self.icon 'today' end diff --git a/app/models/content_types/universe.rb b/app/models/content_types/universe.rb index 0bc312d22..bb70b71ae 100644 --- a/app/models/content_types/universe.rb +++ b/app/models/content_types/universe.rb @@ -70,6 +70,10 @@ def self.color 'purple' end + def self.hex_color + '#9C27B0' + end + def self.icon 'language' end diff --git a/app/models/content_types/vehicle.rb b/app/models/content_types/vehicle.rb index 02181fc47..c2f349660 100644 --- a/app/models/content_types/vehicle.rb +++ b/app/models/content_types/vehicle.rb @@ -21,6 +21,10 @@ def self.color 'text-lighten-2 green' end + def self.hex_color + '#81C784' + end + def self.icon 'drive_eta' end diff --git a/app/models/document.rb b/app/models/document.rb index c079356c6..893473bdd 100644 --- a/app/models/document.rb +++ b/app/models/document.rb @@ -10,6 +10,10 @@ def self.color 'teal' end + def self.hex_color + '#009688' + end + def self.icon 'description' end diff --git a/app/services/forums_linkbuilder_service.rb b/app/services/forums_linkbuilder_service.rb new file mode 100644 index 000000000..32ec8e7d5 --- /dev/null +++ b/app/services/forums_linkbuilder_service.rb @@ -0,0 +1,30 @@ +class ForumsLinkbuilderService < Service + def self.worldbuilding_url(page_type) + self.content_to_url_map.fetch(page_type.name.to_sym, nil) + end + + def self.content_to_url_map + { + 'Character': '/forum/characters-board', + 'Condition': '/forum/conditions', + 'Creature': '/forum/characters', # [sic] + 'Flora': '/forum/flora', + 'Government': '/forum/governments', + 'Item': '/forum/items', + 'Job': '/forum/jobs', + 'Landmark': '/forum/landmarks', + 'Language': '/forum/general-worldbuilding', # wtf did I do + 'Location': '/forum/locations', + 'Magic': '/forum/magic', + 'Planet': '/forum/planets', + 'Race': '/forum/races', + 'Religion': '/forum/religions', + 'Technology': '/forum/technology', + 'Tradition': '/forum/traditions' + } + end + + def self.is_discussions_page?(url) + return url.start_with?('/forum/') + end +end diff --git a/app/views/cards/serendipitous/_content_question.html.erb b/app/views/cards/serendipitous/_content_question.html.erb index e4052fd9c..f7e11d224 100644 --- a/app/views/cards/serendipitous/_content_question.html.erb +++ b/app/views/cards/serendipitous/_content_question.html.erb @@ -34,12 +34,14 @@ questionable_field_ids = fields_for_these_categories.pluck(:id) - attribute_fields_with_values attribute_field_to_question = AttributeField.find_by(id: questionable_field_ids.sample) end + + @serendipitous_asking_question = attribute_field_to_question.present? %> -<% if attribute_field_to_question.present? %> +<% if @serendipitous_asking_question %>
+ <%= render partial: 'content/display/quick_reference', locals: { content: content } %> +
- There have been <%= Thredded::Topic.where('created_at > ?', DateTime.current - 1.week).count %> new threads created in the past week on the forums. - Share your characters, talk about worlbuilding, find a collaborator or two, or just, well, chat! There's threads for everyone. -
- Pages can be "un-deleted" for up to 24 hours after deletion. - After this time, they are permanently deleted and cannot be recovered. - Use this page if you've accidentally deleted a page and need to recover it. -
++ Pages can be "un-deleted" for up to 24 hours after deletion. + After this time, they are permanently deleted and cannot be recovered. + Use this page if you've accidentally deleted a page and need to recover it. +
+-
- - - - <%= form_for content do |f| %> - <%= f.hidden_field :deleted_at, value: nil %> - <%= f.submit 'Restore this page (undelete)', class: 'white btn black-text' %> - <% end %> - -+
+ + + + <%= form_for content do |f| %> + <%= f.hidden_field :deleted_at, value: nil %> + <%= f.submit 'Recover', class: 'white btn black-text' %> + <% end %> + ++ Looks like you haven't deleted any pages in the past 24 hours. If you do, they will show up here for a limited time. +
<% end %> -- Looks like you haven't deleted any pages in the past 24 hours. If you do, they will show up here for a limited time. -
-<% end %> + +
-
- <%= attribute_field.label %>
-
- |
- <%= content.send(attribute_field.name) %> | -
- More information will automatically appear here as you add it to <%= content.name %>. - | -
<%= field[:label] %> | ++ <% if field[:type] == 'universe' %> + <%= link_to serialized_content.data[:universe][:name], universe_path(field[:value]) %> + <% else %> + <%= field[:value] %> + <% end %> + | +
- <%# content.description %> -
- <% if user_signed_in? %>