diff --git a/.rubocop.yml b/.rubocop.yml index 3e0d86588b2..98ae8d56834 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -154,6 +154,8 @@ Rails/OutputSafety: Rails/Output: Exclude: + # Allow patches to print warnings to console: + - 'config/initializers/monkeypatches/*.rb' # Allow migrations to print pt-osc comments to console: - 'db/migrate/*.rb' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a9a71a4b64d..b9aa8fd30ca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ ## Reporting bugs -We maintain a [Jira issue tracker](https://otwarchive.atlassian.net) for developers, +We maintain a [Jira issue tracker](https://otwarchive.atlassian.net/projects/AO3/issues) for developers, and a [list of Known Issues](https://archiveofourown.org/known_issues) for [Archive of Our Own](https://archiveofourown.org) users, neither of which are publicly editable. @@ -35,30 +35,21 @@ with the exception of spelling corrections and documentation improvements (e.g. any Markdown files). We also do not accept code generated by AI tools; for more information, please refer to [our commit policy](https://github.com/otwcode/otwarchive/wiki/Commit-Policy#scary-legal-stuff). -If you'd like the ability to comment on, assign, and transition issues, -you're welcome to create a Jira account! (It makes things a bit easier for us -on the organizational side if the Full Name on your Jira account either closely -matches the name you'd like us to credit in the release notes or includes it in -parentheses, e.g. "Nickname (CREDIT NAME).") We'll give you permissions when -you create your first pull request. - Please check out our development wiki for more information on: - [how to set up a development environment](https://github.com/otwcode/otwarchive/wiki) - [code conventions](https://github.com/otwcode/otwarchive/wiki/Commit-policy) -Please follow the checklist on [our template](https://github.com/otwcode/otwarchive/blob/master/.github/PULL_REQUEST_TEMPLATE.md) when submitting pull requests. - -Please be patient with us! Due to our workload, it may take some time before we -can review and eventually merge your pull request. - -Once your pull request is merged, it will be deployed to our internal testing site -and our QA team will check that everything is working as intended. If not, we may -set the issue to ["Broken on Test"](https://github.com/otwcode/otwarchive/wiki/Issue-Tracking-with-Jira) -and ask you to make further changes in new pull requests. +### Workflow -If all is well, your contribution will be deployed to the [Archive of Our Own](https://archiveofourown.org) -and you will be credited in the [release notes](https://archiveofourown.org/admin_posts?tag=1)! +1. If you're a new contributor, find a task on the [issues reserved for first timers](https://otwarchive.atlassian.net/issues/?filter=13119). Otherwise, or if you're up for a challenge, pick a task from the general [open and unassigned issues](https://otwarchive.atlassian.net/issues/?filter=10800). (If you a new contributor, don't worry about claiming the issue for now. If you make a Jira account, you'll get permissions for claiming issues in step 5.) +2. Write code to address the issue. +3. Optional: Create a Jira account if you'd like the ability to comment on, assign, and transition issues. Please make sure the Full Name on your Jira account either closely matches the name you'd like us to credit in the release notes or includes it in parentheses, e.g. "Nickname (CREDIT NAME)." +4. Submit the code with a pull request following the checklist on [our template](https://github.com/otwcode/otwarchive/blob/master/.github/PULL_REQUEST_TEMPLATE.md). +5. Once you've submitted a pull request, we'll review your code and give you permissions on Jira. Please be patient with us! Due to our workload, it may take some time before we can review and eventually merge your pull request. +6. Once your pull request is merged, we will deploy it to our internal testing site and our QA team will check that everything is working as intended. +7. If something is not working as intended, we may set the issue to ["Broken on Test"](https://github.com/otwcode/otwarchive/wiki/Issue-Tracking-with-Jira) and ask you to make further changes in new pull requests. +8. If all is well, your contribution will be deployed to the [Archive of Our Own](https://archiveofourown.org) and you will be credited in the [release notes](https://archiveofourown.org/admin_posts?tag=1)! ## Volunteering for the OTW diff --git a/Gemfile.lock b/Gemfile.lock index a4e628b9c13..71edb8fe7fb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -24,75 +24,75 @@ GEM remote: https://rubygems.org/ specs: aaronh-chronic (0.3.9) - actioncable (7.0.8.5) - actionpack (= 7.0.8.5) - activesupport (= 7.0.8.5) + actioncable (7.0.8.7) + actionpack (= 7.0.8.7) + activesupport (= 7.0.8.7) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.8.5) - actionpack (= 7.0.8.5) - activejob (= 7.0.8.5) - activerecord (= 7.0.8.5) - activestorage (= 7.0.8.5) - activesupport (= 7.0.8.5) + actionmailbox (7.0.8.7) + actionpack (= 7.0.8.7) + activejob (= 7.0.8.7) + activerecord (= 7.0.8.7) + activestorage (= 7.0.8.7) + activesupport (= 7.0.8.7) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.8.5) - actionpack (= 7.0.8.5) - actionview (= 7.0.8.5) - activejob (= 7.0.8.5) - activesupport (= 7.0.8.5) + actionmailer (7.0.8.7) + actionpack (= 7.0.8.7) + actionview (= 7.0.8.7) + activejob (= 7.0.8.7) + activesupport (= 7.0.8.7) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.0) - actionpack (7.0.8.5) - actionview (= 7.0.8.5) - activesupport (= 7.0.8.5) + actionpack (7.0.8.7) + actionview (= 7.0.8.7) + activesupport (= 7.0.8.7) rack (~> 2.0, >= 2.2.4) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) actionpack-page_caching (1.2.4) actionpack (>= 4.0.0) - actiontext (7.0.8.5) - actionpack (= 7.0.8.5) - activerecord (= 7.0.8.5) - activestorage (= 7.0.8.5) - activesupport (= 7.0.8.5) + actiontext (7.0.8.7) + actionpack (= 7.0.8.7) + activerecord (= 7.0.8.7) + activestorage (= 7.0.8.7) + activesupport (= 7.0.8.7) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.8.5) - activesupport (= 7.0.8.5) + actionview (7.0.8.7) + activesupport (= 7.0.8.7) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) active_record_query_trace (1.8.2) activerecord (>= 6.0.0) - activejob (7.0.8.5) - activesupport (= 7.0.8.5) + activejob (7.0.8.7) + activesupport (= 7.0.8.7) globalid (>= 0.3.6) - activemodel (7.0.8.5) - activesupport (= 7.0.8.5) + activemodel (7.0.8.7) + activesupport (= 7.0.8.7) activemodel-serializers-xml (1.0.2) activemodel (> 5.x) activesupport (> 5.x) builder (~> 3.1) - activerecord (7.0.8.5) - activemodel (= 7.0.8.5) - activesupport (= 7.0.8.5) - activestorage (7.0.8.5) - actionpack (= 7.0.8.5) - activejob (= 7.0.8.5) - activerecord (= 7.0.8.5) - activesupport (= 7.0.8.5) + activerecord (7.0.8.7) + activemodel (= 7.0.8.7) + activesupport (= 7.0.8.7) + activestorage (7.0.8.7) + actionpack (= 7.0.8.7) + activejob (= 7.0.8.7) + activerecord (= 7.0.8.7) + activesupport (= 7.0.8.7) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (7.0.8.5) + activesupport (7.0.8.7) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -257,7 +257,7 @@ GEM rainbow rubocop smart_properties - erubi (1.13.0) + erubi (1.13.1) escape_utils (1.2.1) et-orbi (1.2.11) tzinfo @@ -435,22 +435,22 @@ GEM rack-protection (3.2.0) base64 (>= 0.1.0) rack (~> 2.2, >= 2.2.4) - rack-test (2.1.0) + rack-test (2.2.0) rack (>= 1.3) - rails (7.0.8.5) - actioncable (= 7.0.8.5) - actionmailbox (= 7.0.8.5) - actionmailer (= 7.0.8.5) - actionpack (= 7.0.8.5) - actiontext (= 7.0.8.5) - actionview (= 7.0.8.5) - activejob (= 7.0.8.5) - activemodel (= 7.0.8.5) - activerecord (= 7.0.8.5) - activestorage (= 7.0.8.5) - activesupport (= 7.0.8.5) + rails (7.0.8.7) + actioncable (= 7.0.8.7) + actionmailbox (= 7.0.8.7) + actionmailer (= 7.0.8.7) + actionpack (= 7.0.8.7) + actiontext (= 7.0.8.7) + actionview (= 7.0.8.7) + activejob (= 7.0.8.7) + activemodel (= 7.0.8.7) + activerecord (= 7.0.8.7) + activestorage (= 7.0.8.7) + activesupport (= 7.0.8.7) bundler (>= 1.15.0) - railties (= 7.0.8.5) + railties (= 7.0.8.7) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -459,15 +459,15 @@ GEM activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.1) + rails-html-sanitizer (1.6.2) loofah (~> 2.21) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) rails-i18n (7.0.8) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) - railties (7.0.8.5) - actionpack (= 7.0.8.5) - activesupport (= 7.0.8.5) + railties (7.0.8.7) + actionpack (= 7.0.8.7) + activesupport (= 7.0.8.7) method_source rake (>= 12.2) thor (~> 1.0) diff --git a/README.md b/README.md index b7234cdb7a2..8724d779bc5 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ We welcome pull requests for bugs described in our issue tracker. Please see our We do not have a public chat, but you are welcome to contact us at otw-coders@transformativeworks.org if you have any questions. +We grant your Jira account permissions for commenting on, assigning, and transitioning issues [after you create your first pull request](https://github.com/otwcode/otwarchive/blob/master/CONTRIBUTING.md#workflow). + API ---------- There is currently no API for the OTW-Archive software. While it is something we're considering for the future, we ask that contributors instead focus on issues already in our [Jira issue tracker](https://otwarchive.atlassian.net/). diff --git a/app/controllers/chapters_controller.rb b/app/controllers/chapters_controller.rb index 3fe5a4478ad..bdab981c760 100644 --- a/app/controllers/chapters_controller.rb +++ b/app/controllers/chapters_controller.rb @@ -1,6 +1,6 @@ class ChaptersController < ApplicationController # only registered users and NOT admin should be able to create new chapters - before_action :users_only, except: [ :index, :show, :destroy, :confirm_delete ] + before_action :users_only, except: [:index, :show, :destroy, :confirm_delete] before_action :check_user_status, only: [:new, :create, :update, :update_positions] before_action :check_user_not_suspended, only: [:edit, :confirm_delete, :destroy] before_action :load_work @@ -28,53 +28,55 @@ def manage # GET /work/:work_id/chapters/:id.xml def show @tag_groups = @work.tag_groups - if params[:view_adult] - cookies[:view_adult] = "true" - elsif @work.adult? && !see_adult? - render "works/_adult", layout: "application" and return - end - if params[:selected_id] - redirect_to url_for(controller: :chapters, action: :show, work_id: @work.id, id: params[:selected_id]) and return - end + redirect_to url_for(controller: :chapters, action: :show, work_id: @work.id, id: params[:selected_id]) and return if params[:selected_id] + @chapters = @work.chapters_in_order( include_content: false, include_drafts: (logged_in_as_admin? || @work.user_is_owner_or_invited?(current_user)) ) - if !@chapters.include?(@chapter) + + unless @chapters.include?(@chapter) access_denied + return + end + + chapter_position = @chapters.index(@chapter) + if @chapters.length > 1 + @previous_chapter = @chapters[chapter_position - 1] unless chapter_position.zero? + @next_chapter = @chapters[chapter_position + 1] + end + + if @work.unrevealed? + @page_title = t(".unrevealed") + t(".chapter_position", position: @chapter.position.to_s) else - chapter_position = @chapters.index(@chapter) - if @chapters.length > 1 - @previous_chapter = @chapters[chapter_position-1] unless chapter_position == 0 - @next_chapter = @chapters[chapter_position+1] - end + fandoms = @tag_groups["Fandom"] + fandom = fandoms.empty? ? t(".unspecified_fandom") : fandoms[0].name + title_fandom = fandoms.size > 3 ? t(".multifandom") : fandom + author = @work.anonymous? ? t(".anonymous") : @work.pseuds.sort.collect(&:byline).join(", ") + @page_title = get_page_title(title_fandom, author, @work.title + t(".chapter_position", position: @chapter.position.to_s)) + end - if @work.unrevealed? - @page_title = t(".unrevealed") + t(".chapter_position", position: @chapter.position.to_s) - else - fandoms = @tag_groups["Fandom"] - fandom = fandoms.empty? ? t(".unspecified_fandom") : fandoms[0].name - title_fandom = fandoms.size > 3 ? t(".multifandom") : fandom - author = @work.anonymous? ? t(".anonymous") : @work.pseuds.sort.collect(&:byline).join(", ") - @page_title = get_page_title(title_fandom, author, @work.title + t(".chapter_position", position: @chapter.position.to_s)) - end + if params[:view_adult] + cookies[:view_adult] = "true" + elsif @work.adult? && !see_adult? + render "works/_adult", layout: "application" and return + end - @kudos = @work.kudos.with_user.includes(:user) + @kudos = @work.kudos.with_user.includes(:user) - if current_user.respond_to?(:subscriptions) - @subscription = current_user.subscriptions.where(subscribable_id: @work.id, - subscribable_type: 'Work').first || - current_user.subscriptions.build(subscribable: @work) - end - # update the history. - Reading.update_or_create(@work, current_user) if current_user + if current_user.respond_to?(:subscriptions) + @subscription = current_user.subscriptions.where(subscribable_id: @work.id, + subscribable_type: "Work").first || + current_user.subscriptions.build(subscribable: @work) + end + # update the history. + Reading.update_or_create(@work, current_user) if current_user - respond_to do |format| - format.html - format.js - end + respond_to do |format| + format.html + format.js end end @@ -86,14 +88,14 @@ def new # GET /work/:work_id/chapters/1/edit def edit - if params["remove"] == "me" - @chapter.creatorships.for_user(current_user).destroy_all - if @work.chapters.any? { |c| current_user.is_author_of?(c) } - flash[:notice] = ts("You have been removed as a creator from the chapter.") - redirect_to @work - else # remove from work if no longer co-creator on any chapter - redirect_to edit_work_path(@work, remove: "me") - end + return unless params["remove"] == "me" + + @chapter.creatorships.for_user(current_user).destroy_all + if @work.chapters.any? { |c| current_user.is_author_of?(c) } + flash[:notice] = ts("You have been removed as a creator from the chapter.") + redirect_to @work + else # remove from work if no longer co-creator on any chapter + redirect_to edit_work_path(@work, remove: "me") end end @@ -250,7 +252,7 @@ def chapter_cannot_be_saved? # fetch work these chapters belong to from db def load_work @work = params[:work_id] ? Work.find_by(id: params[:work_id]) : Chapter.find_by(id: params[:id]).try(:work) - unless @work.present? + if @work.blank? flash[:error] = ts("Sorry, we couldn't find the work you were looking for.") redirect_to root_path and return end @@ -263,18 +265,15 @@ def load_work def load_chapter @chapter = @work.chapters.find_by(id: params[:id]) - unless @chapter - flash[:error] = ts("Sorry, we couldn't find the chapter you were looking for.") - redirect_to work_path(@work) - end - end + return if @chapter + flash[:error] = ts("Sorry, we couldn't find the chapter you were looking for.") + redirect_to work_path(@work) + end def post_chapter - if !@work.posted - @work.update_attribute(:posted, true) - end - flash[:notice] = ts('Chapter has been posted!') + @work.update_attribute(:posted, true) unless @work.posted + flash[:notice] = ts("Chapter has been posted!") end private @@ -284,6 +283,5 @@ def chapter_params :"published_at(2i)", :"published_at(1i)", :summary, :notes, :endnotes, :content, :published_at, author_attributes: [:byline, ids: [], coauthors: []]) - end end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index edff4637cab..86e83630c1e 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -8,24 +8,24 @@ def unicorn_test end def content - @page_title = t(".page_title") + @page_subtitle = t(".page_title") render action: "content", layout: "application" end def privacy - @page_title = t(".page_title") + @page_subtitle = t(".page_title") render action: "privacy", layout: "application" end # terms of service def tos - @page_title = t(".page_title") + @page_subtitle = t(".page_title") render action: "tos", layout: "application" end # terms of service faq def tos_faq - @page_title = t(".page_title") + @page_subtitle = t(".page_title") render action: "tos_faq", layout: "application" end diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb index fd87f3e7946..0285291d0bb 100644 --- a/app/helpers/comments_helper.rb +++ b/app/helpers/comments_helper.rb @@ -210,6 +210,10 @@ def can_review_comment?(comment) is_author_of?(comment.ultimate_parent) || policy(comment).can_review_comment? end + def can_review_all_comments?(commentable) + commentable.is_a?(AdminPost) || is_author_of?(commentable) + end + #### HELPERS FOR REPLYING TO COMMENTS ##### # return link to add new reply to a comment diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb index 2669e1699ef..56ac370dbb4 100644 --- a/app/helpers/tags_helper.rb +++ b/app/helpers/tags_helper.rb @@ -240,7 +240,9 @@ def show_hidden_tag_link_list_item(item, category, options = {}) def get_title_string(tags, category_name = "") if tags && tags.size > 0 - tags.collect(&:name).join(", ") + # We don't use .to_sentence because these aren't links and we risk making any + # connector word (e.g., "and") look like part of the final tag. + tags.pluck(:name).join(t("support.array.words_connector")) elsif tags.blank? && category_name.blank? "Choose Not To Use Archive Warnings" else diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index ebe3070ebf9..1eb33ced20f 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -149,12 +149,10 @@ def batch_subscription_notification(subscription_id, entries) def invite_increase_notification(user_id, total) @user = User.find(user_id) @total = total - I18n.with_locale(@user.preference.locale.iso) do - mail( - to: @user.email, - subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME) - ) - end + mail( + to: @user.email, + subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME) + ) end # Emails a user to say that their request for invitation codes has been declined @@ -199,14 +197,12 @@ def potential_match_generation_notification(collection_id, email) def challenge_assignment_notification(collection_id, assigned_user_id, assignment_id) @collection = Collection.find(collection_id) @assigned_user = User.find(assigned_user_id) - assignment = ChallengeAssignment.find(assignment_id) - @request = (assignment.request_signup || assignment.pinch_request_signup) - I18n.with_locale(@assigned_user.preference.locale.iso) do - mail( - to: @assigned_user.email, - subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) - ) - end + @assignment = ChallengeAssignment.find(assignment_id) + @request = (@assignment.request_signup || @assignment.pinch_request_signup) + mail( + to: @assigned_user.email, + subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) + ) end # Asks a user to validate and activate their new account diff --git a/app/models/challenge_assignment.rb b/app/models/challenge_assignment.rb index 80b37738451..714fecdf537 100755 --- a/app/models/challenge_assignment.rb +++ b/app/models/challenge_assignment.rb @@ -271,7 +271,11 @@ def send_out (self.pinch_hitter ? self.pinch_hitter.user : nil) end request = self.request_signup || self.pinch_request_signup - UserMailer.challenge_assignment_notification(collection.id, assigned_to.id, self.id).deliver_later if assigned_to && request + if assigned_to && request + I18n.with_locale(assigned_to.preference.locale.iso) do + UserMailer.challenge_assignment_notification(collection.id, assigned_to.id, self.id).deliver_later + end + end end end diff --git a/app/models/concerns/justifiable.rb b/app/models/concerns/justifiable.rb index dea0c09d80c..c4c4df3e8c5 100644 --- a/app/models/concerns/justifiable.rb +++ b/app/models/concerns/justifiable.rb @@ -5,9 +5,12 @@ module Justifiable attr_accessor :ticket_number attr_reader :ticket_url + before_validation :strip_octothorpe validates :ticket_number, presence: true, - numericality: { only_integer: true }, + # i18n-tasks-use t("activerecord.errors.messages.numeric_with_optional_hash") + numericality: { only_integer: true, + message: :numeric_with_optional_hash }, if: :enabled? validate :ticket_number_exists_in_tracker, if: :enabled? @@ -15,6 +18,12 @@ module Justifiable private + def strip_octothorpe + return if ticket_number.is_a?(Integer) + + self.ticket_number = self.ticket_number.delete_prefix("#") unless self.ticket_number.nil? + end + def enabled? # Only require a ticket if the record has been changed by an admin. User.current_user.is_a?(Admin) && changed? diff --git a/app/models/invitation.rb b/app/models/invitation.rb index cc7bb464a88..d8437ab8c7e 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -31,7 +31,9 @@ def self.grant_all(total) total.times do user.invitations.create end - UserMailer.invite_increase_notification(user.id, total).deliver_later + I18n.with_locale(user.preference.locale.iso) do + UserMailer.invite_increase_notification(user.id, total).deliver_later + end end User.out_of_invites.update_all('out_of_invites = 0') end @@ -43,7 +45,9 @@ def self.grant_empty(total) total.times do user.invitations.create end - UserMailer.invite_increase_notification(user.id, total).deliver_later + I18n.with_locale(user.preference.locale.iso) do + UserMailer.invite_increase_notification(user.id, total).deliver_later + end end User.out_of_invites.update_all('out_of_invites = 0') end diff --git a/app/models/story_parser.rb b/app/models/story_parser.rb index 96477074800..2c2e9e69d9e 100644 --- a/app/models/story_parser.rb +++ b/app/models/story_parser.rb @@ -799,6 +799,8 @@ def download_with_timeout(location, limit = 10) # we do a little cleanup here in case the user hasn't included the 'http://' # or if they've used capital letters or an underscore in the hostname uri = UrlFormatter.new(location).standardized + raise Error, I18n.t("story_parser.on_archive") if ArchiveConfig.PERMITTED_HOSTS.include?(uri.host) + response = Net::HTTP.get_response(uri) case response when Net::HTTPSuccess diff --git a/app/models/user_invite_request.rb b/app/models/user_invite_request.rb index 549fbb58955..0095bb24770 100644 --- a/app/models/user_invite_request.rb +++ b/app/models/user_invite_request.rb @@ -26,7 +26,9 @@ def grant_request self.quantity.times do self.user.invitations.create end - UserMailer.invite_increase_notification(self.user.id, self.quantity).deliver_after_commit + I18n.with_locale(self.user.preference.locale.iso) do + UserMailer.invite_increase_notification(self.user.id, self.quantity).deliver_after_commit + end end end end diff --git a/app/views/comments/unreviewed.html.erb b/app/views/comments/unreviewed.html.erb index 51ad90d82e6..f70d57605ec 100644 --- a/app/views/comments/unreviewed.html.erb +++ b/app/views/comments/unreviewed.html.erb @@ -3,10 +3,12 @@ -
+<% if can_review_all_comments?(@commentable) %> + +<% end %> diff --git a/app/views/pseuds/_pseuds_form.html.erb b/app/views/pseuds/_pseuds_form.html.erb index a3d4b95a041..b7b1c1d558c 100644 --- a/app/views/pseuds/_pseuds_form.html.erb +++ b/app/views/pseuds/_pseuds_form.html.erb @@ -62,8 +62,6 @@<%= t(".ticket_footnote") %>
- <% if fandoms %><%= style_bold(Fandom.human_attribute_name("name_with_colon", count: prompt.any_fandom ? 1 : tag_groups["Fandom"].count)) %> <%= fandoms %>
<% end %>
- <% if chars %><%= style_bold(Character.human_attribute_name("name_with_colon", count: prompt.any_character ? 1 : tag_groups["Character"].count)) %> <%= chars %>
<% end %>
- <% if ships %><%= style_bold(Relationship.human_attribute_name("name_with_colon", count: prompt.any_relationship ? 1 : tag_groups["Relationship"].count)) %> <%= ships %>
<% end %>
- <% if ratings %><%= style_bold(Rating.human_attribute_name("name_with_colon")) %> <%= ratings %>
<% end %>
- <% if warnings %><%= style_bold(ArchiveWarning.human_attribute_name("name_with_colon", count: prompt.any_archive_warning ? 1 : tag_groups["ArchiveWarning"].count)) %> <%= warnings %>
<% end %>
- <% if categories %><%= style_bold(Category.human_attribute_name("name_with_colon", count: prompt.any_category ? 1 : tag_groups["Category"].count)) %> <%= categories %>
<% end %>
- <% if atags %><%= style_bold(Freeform.human_attribute_name("name_with_colon", count: prompt.any_freeform ? 1 : tag_groups["Freeform"].count)) %> <%= atags %>
<% end %>
- <% if otags %><%= style_bold("#{t(".optional_tags")}") %> <%= otags %>
<% end %>
- <% if prompt.url && !prompt.url.blank? %><%= style_bold("#{t(".prompt_url")}") %> <%= style_link(prompt.url, prompt.url) %>
<% end %>
+ <% if fandoms %>
+ <%= style_bold(t("activerecord.models.fandom", count: prompt.any_fandom ? 1 : tag_groups["Fandom"].count) + t("mailer.general.metadata_label_indicator")) %>
+ <%= fandoms %>
+
+ <% end %>
+ <% if chars %>
+ <%= style_bold(t("activerecord.models.character", count: prompt.any_character ? 1 : tag_groups["Character"].count) + t("mailer.general.metadata_label_indicator")) %>
+ <%= chars %>
+
+ <% end %>
+ <% if ships %>
+ <%= style_bold(t("activerecord.models.relationship", count: prompt.any_relationship ? 1 : tag_groups["Relationship"].count) + t("mailer.general.metadata_label_indicator")) %>
+ <%= ships %>
+
+ <% end %>
+ <% if ratings %>
+ <%= style_bold(t("activerecord.models.rating", count: 1) + t("mailer.general.metadata_label_indicator")) %>
+ <%= ratings %>
+
+ <% end %>
+ <% if warnings %>
+ <%= style_bold(t("activerecord.models.archive_warning", count: prompt.any_archive_warning ? 1 : tag_groups["ArchiveWarning"].count) + t("mailer.general.metadata_label_indicator")) %>
+ <%= warnings %>
+
+ <% end %>
+ <% if categories %>
+ <%= style_bold(t("activerecord.models.category", count: prompt.any_category ? 1 : tag_groups["Category"].count) + t("mailer.general.metadata_label_indicator")) %>
+ <%= categories %>
+
+ <% end %>
+ <% if atags %>
+ <%= style_bold(t("activerecord.models.freeform", count: prompt.any_freeform ? 1 : tag_groups["Freeform"].count) + t("mailer.general.metadata_label_indicator")) %>
+ <%= atags %>
+
+ <% end %>
+ <% if otags %>
+ <%= style_bold(t(".optional_tags")) %>
+ <%= otags %>
+
+ <% end %>
+ <% if prompt.url && !prompt.url.blank? %>
+ <%= style_bold(t(".prompt_url")) %>
+ <%= style_link(prompt.url, prompt.url) %>
+
+ <% end %>
<% if prompt.description && !prompt.description.blank? %>
<%= style_bold(t(".description")) %>
<%= style_quote(prompt.description) %>
@@ -50,7 +86,7 @@
<%= style_bold(t(".due")) %> <%= time_in_zone(@collection.challenge.assignments_due_at, (@collection.challenge.time_zone || Time.zone.name), @assigned_user) %>.
<%= t(".html.look_up", link: style_link(t(".html.look_up_link"), user_assignments_url(@assigned_user))).html_safe %>
+<%= t(".look_up.html", your_assignments_link: style_link(t(".look_up.your_assignments"), user_assignments_url(@assigned_user))) %>
<% if @collection && !@collection.assignment_notification.blank? %><%= escape_html_and_create_linebreaks(@collection.assignment_notification) %>
@@ -58,9 +94,9 @@ <% end %> <% content_for :footer_note do %> - <%= t(".html.footer", title: style_footer_link(@collection.title, collection_url(@collection)), footer_link: style_footer_link(t(".html.footer_link"), collection_profile_url(@collection))).html_safe %> + <%= t(".footer.html", title: style_footer_link(@collection.title, collection_url(@collection)), challenge_profile_link: style_footer_link(t(".footer.challenge_profile"), collection_profile_url(@collection))) %> <% end %> <% content_for :sent_at do %> - <%= l(Time.now) %> + <%= l(@assignment.sent_at) %> <% end %> diff --git a/app/views/user_mailer/challenge_assignment_notification.text.erb b/app/views/user_mailer/challenge_assignment_notification.text.erb index 8cb06b561f4..f7db169b07d 100644 --- a/app/views/user_mailer/challenge_assignment_notification.text.erb +++ b/app/views/user_mailer/challenge_assignment_notification.text.erb @@ -1,5 +1,5 @@ <% content_for :message do %> -<%= t ".text.assignment", collection_title: @collection.title, collection_url: collection_url(@collection) %> +<%= t ".assignment.text", collection_title: @collection.title, collection_url: collection_url(@collection) %> <%= t ".recipient" %> <%= @request.nil? ? t(".recipient_missing") : text_pseud(@request.pseud) %> @@ -22,26 +22,50 @@ <%= index + 1 %>. <%= prompt.title %> -<% if fandoms %><%= Fandom.human_attribute_name("name_with_colon", count: prompt.any_fandom ? 1 : tag_groups["Fandom"].count) %> <%= fandoms %><% end %><% if chars %> -<%= Character.human_attribute_name("name_with_colon", count: prompt.any_character ? 1 : tag_groups["Character"].count) %> <%= chars %><% end %><% if ships %> -<%= Relationship.human_attribute_name("name_with_colon", count: prompt.any_relationship ? 1 : tag_groups["Relationship"].count) %> <%= ships %><% end %><% if ratings %> -<%= Rating.human_attribute_name("name_with_colon") %> <%= ratings %><% end %><% if warnings %> -<%= ArchiveWarning.human_attribute_name("name_with_colon", count: prompt.any_archive_warning ? 1 : tag_groups["ArchiveWarning"].count) %> <%= warnings %><% end %><% if categories %> -<%= Category.human_attribute_name("name_with_colon", count: prompt.any_category ? 1 : tag_groups["Category"].count) %> <%= categories %><% end %><% if atags %> -<%= Freeform.human_attribute_name("name_with_colon", count: prompt.any_freeform ? 1 : tag_groups["Freeform"].count) %> <%= atags %><% end %><% if otags %> -<%= t ".optional_tags" %> <%= otags %><% end %><% if prompt.url && !prompt.url.blank? %> -<%= t ".prompt_url" %> <%= prompt.url %><% end %><% if prompt.description && !prompt.description.blank? %> -<%= t ".description" %> - <%= to_plain_text(prompt.description) %><% end %> +<% if fandoms %> +<%= t("activerecord.models.fandom", count: prompt.any_fandom ? 1 : tag_groups["Fandom"].count) + t("mailer.general.metadata_label_indicator") %><%= fandoms %> +<% end %> +<% if chars %> +<%= t("activerecord.models.character", count: prompt.any_character ? 1 : tag_groups["Character"].count) + t("mailer.general.metadata_label_indicator") %><%= chars %> +<% end %> +<% if ships %> +<%= t("activerecord.models.relationship", count: prompt.any_relationship ? 1 : tag_groups["Relationship"].count) + t("mailer.general.metadata_label_indicator") %><%= ships %> +<% end %> +<% if ratings %> +<%= t("activerecord.models.rating", count: 1) + t("mailer.general.metadata_label_indicator") %><%= ratings %> +<% end %> +<% if warnings %> +<%= t("activerecord.models.archive_warning", count: prompt.any_archive_warning ? 1 : tag_groups["ArchiveWarning"].count) + t("mailer.general.metadata_label_indicator") %><%= warnings %> +<% end %> +<% if categories %> +<%= t("activerecord.models.category", count: prompt.any_category ? 1 : tag_groups["Category"].count) + t("mailer.general.metadata_label_indicator") %><%= categories %> +<% end %> +<% if atags %> +<%= t("activerecord.models.freeform", count: prompt.any_freeform ? 1 : tag_groups["Freeform"].count) + t("mailer.general.metadata_label_indicator") %><%= atags %> +<% end %> +<% if otags %> +<%= t(".optional_tags") %> <%= otags %> +<% end %> +<% if prompt.url && !prompt.url.blank? %> +<%= t(".prompt_url") %> <%= prompt.url %> +<% end %> +<% if prompt.description && !prompt.description.blank? %> +<%= t(".description") %> + <%= to_plain_text(prompt.description) %> +<% end %> <% end %><%= text_divider %> -<%= t '.due' %> <%= to_plain_text(time_in_zone(@collection.challenge.assignments_due_at, (@collection.challenge.time_zone || Time.zone.name), @assigned_user)).gsub(/\n\s*/, "") %>. +<%= t(".due") %> <%= to_plain_text(time_in_zone(@collection.challenge.assignments_due_at, (@collection.challenge.time_zone || Time.zone.name), @assigned_user)).gsub(/\n\s*/, "") %>. -<%= t ".text.look_up", link: user_assignments_url(@assigned_user) %> +<%= t(".look_up.text", your_assignments_url: user_assignments_url(@assigned_user)) %> <% if @collection && !@collection.assignment_notification.blank? %> <%= @collection.assignment_notification %><% end %><% end %> -<% content_for :footer_note do %><%= t ".text.footer", title: @collection.title, url: collection_url(@collection), profile_url: collection_profile_url(@collection) %><% end %> -<% content_for :sent_at do %><%= l(Time.now) %><% end %> +<% content_for :footer_note do %> +<%= t(".footer.text", title: @collection.title, url: collection_url(@collection), challenge_profile_url: collection_profile_url(@collection)) -%> +<% end %> +<% content_for :sent_at do %> +<%= l(@assignment.sent_at) -%> +<% end %> diff --git a/app/views/user_mailer/invite_increase_notification.html.erb b/app/views/user_mailer/invite_increase_notification.html.erb index 28f3ec28dfb..eb5036e5deb 100644 --- a/app/views/user_mailer/invite_increase_notification.html.erb +++ b/app/views/user_mailer/invite_increase_notification.html.erb @@ -1,7 +1,7 @@ <% content_for :message do %><%= t("mailer.general.greeting.informal.addressed_html", name: style_bold(@user.login)) %>
-<%= t(".html.body", count: @total, invitation_page_link: style_link(t(".invitation_page_link_text"), user_invitations_url(@user))).html_safe %>
+<%= t(".body.html", count: @total, invitation_page_link: style_link(t(".invitation_page_link_text"), user_invitations_url(@user))) %>
<%= t("mailer.general.closing.informal") %>
diff --git a/app/views/user_mailer/invite_increase_notification.text.erb b/app/views/user_mailer/invite_increase_notification.text.erb
index 71db974dd6d..499d6c02e2c 100644
--- a/app/views/user_mailer/invite_increase_notification.text.erb
+++ b/app/views/user_mailer/invite_increase_notification.text.erb
@@ -1,7 +1,7 @@
<% content_for :message do %>
<%= t("mailer.general.greeting.informal.addressed_html", name: @user.login) %>
-<%= t(".text.body", count: @total, invitation_page_url: user_invitations_url(@user)) %>
+<%= t(".body.text", count: @total, invitation_page_url: user_invitations_url(@user)) %>
<%= t("mailer.general.closing.informal") %>
<%= t("mailer.general.signature.app_short_name") %>
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb
index 9f308eb0c11..e9a5c2d42f8 100644
--- a/app/views/users/edit.html.erb
+++ b/app/views/users/edit.html.erb
@@ -46,8 +46,6 @@
<%= t(".admin.ticket_number.numbers_only") %>
- We allow external image URLs (specified as url('http://somesite.com/my_awesome_image.jpg')
) in JPG, GIF, and PNG formats.
+ We allow external image URLs (specified as url('https://example.com/my_awesome_image.jpg')
) in JPG, GIF, and PNG formats.
Please note, however, that skins using external images will not be approved for public use.