diff --git a/app/assets/javascripts/markdown.js b/app/assets/javascripts/markdown.js index b09b69a24..b31bd2d6b 100644 --- a/app/assets/javascripts/markdown.js +++ b/app/assets/javascripts/markdown.js @@ -15,6 +15,16 @@ $(() => { $field.val(prev.substring(0, $field[0].selectionStart) + text + prev.substring($field[0].selectionEnd)); }; + + $('.js-template').on('click', async ev => { + const $postField = $('.js-post-field'); + $tgt = $(ev.target); + const content = $(`#template-md-${$tgt.attr('data-template-id')}`).val(); + replaceSelection($postField, content); + $postField.trigger('markdown'); + $tgt.parents('.modal,.droppanel').removeClass('is-active'); + }); + $(document).on('click', '.js-markdown-tool', ev => { const $tgt = $(ev.target); const $button = $tgt.is('a') ? $tgt : $tgt.parents('a'); diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 44a2e1d21..ad5e5b2d2 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -133,7 +133,6 @@ hr { } .modal { - position: fixed !important; z-index: 8998; } diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index efa5963ca..7a02fc1a8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -292,7 +292,7 @@ def pull_pinned_links_and_hot_questions def pull_categories @header_categories = Rails.cache.fetch('header_categories') do - Category.all.order(sequence: :asc, id: :asc) + Category.where.not(sequence: -1).order(sequence: :asc, id: :asc) end end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 539b80458..b83d59915 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -161,7 +161,8 @@ def show def edit; end def update - before = { body: @post.body_markdown, title: @post.title, tags: @post.tags.to_a } + before = { body: @post.body_markdown, title: @post.title, tags: @post.tags.to_a, +template_post_type: @post.template_post_type } body_rendered = helpers.post_markdown(:post, :body_markdown) new_tags_cache = params[:post][:tags_cache]&.reject(&:empty?) @@ -184,7 +185,9 @@ def update PostHistory.post_edited(post, current_user, before: before[:body], after: @post.body_markdown, comment: params[:edit_comment], before_title: before[:title], after_title: @post.title, - before_tags: before[:tags], after_tags: @post.tags) + before_tags: before[:tags], after_tags: @post.tags, + before_template_post_type: before[:template_post_type], + after_template_post_type: @post.template_post_type) end flash[:success] = "#{helpers.pluralize(posts.to_a.size, 'post')} updated." redirect_to help_path(slug: @post.doc_slug) @@ -196,7 +199,9 @@ def update PostHistory.post_edited(@post, current_user, before: before[:body], after: @post.body_markdown, comment: params[:edit_comment], before_title: before[:title], after_title: @post.title, - before_tags: before[:tags], after_tags: @post.tags) + before_tags: before[:tags], after_tags: @post.tags, + before_template_post_type: before[:template_post_type], + after_template_post_type: @post.template_post_type) if params[:redact] # Hide all previous history @@ -541,7 +546,7 @@ def delete_draft def permitted [:post_type_id, :category_id, :parent_id, :title, :body_markdown, :license_id, - :doc_slug, :help_category, :help_ordering] + :doc_slug, :help_category, :help_ordering, :template_post_type_id] end def post_params diff --git a/app/models/post.rb b/app/models/post.rb index aecc13bd3..da1484eb8 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -14,6 +14,7 @@ class Post < ApplicationRecord belongs_to :license, optional: true belongs_to :close_reason, optional: true belongs_to :duplicate_post, class_name: 'Question', optional: true + belongs_to :template_post_type, class_name: 'PostType', optional: true has_and_belongs_to_many :tags, dependent: :destroy has_many :votes, dependent: :destroy has_many :comments, dependent: :destroy @@ -64,7 +65,7 @@ def self.search(term) # Double-define: initial definitions are less efficient, so if we have a record of the post type we'll # override them later with more efficient methods. - ['Question', 'Answer', 'PolicyDoc', 'HelpDoc', 'Article'].each do |pt| + ['Question', 'Answer', 'PolicyDoc', 'HelpDoc', 'Article', 'PostTemplate'].each do |pt| define_method "#{pt.underscore}?" do post_type_id == pt.constantize.post_type_id end diff --git a/app/models/post_history.rb b/app/models/post_history.rb index 73b2e715a..7970befee 100644 --- a/app/models/post_history.rb +++ b/app/models/post_history.rb @@ -1,5 +1,7 @@ class PostHistory < ApplicationRecord include PostRelated + belongs_to :before_template_post_type, class_name: 'PostType', optional: true + belongs_to :after_template_post_type, class_name: 'PostType', optional: true belongs_to :post_history_type belongs_to :user has_many :post_history_tags @@ -25,7 +27,8 @@ def self.method_missing(name, *args, **opts) end object, user = args - fields = [:before, :after, :comment, :before_title, :after_title, :before_tags, :after_tags, :hidden] + fields = [:before, :after, :comment, :before_title, :after_title, :before_tags, :after_tags, :hidden, + :before_template_post_type, :after_template_post_type] values = fields.to_h { |f| [f, nil] }.merge(opts) history_type_name = name.to_s @@ -37,7 +40,8 @@ def self.method_missing(name, *args, **opts) params = { post_history_type: history_type, user: user, post: object, community_id: object.community_id } { before: :before_state, after: :after_state, comment: :comment, before_title: :before_title, - after_title: :after_title, hidden: :hidden }.each do |arg, attr| + after_title: :after_title, hidden: :hidden, before_template_post_type: :before_template_post_type, + after_template_post_type: :after_template_post_type }.each do |arg, attr| next if values[arg].nil? params = params.merge(attr => values[arg]) diff --git a/app/models/post_template.rb b/app/models/post_template.rb new file mode 100644 index 000000000..72ce63757 --- /dev/null +++ b/app/models/post_template.rb @@ -0,0 +1,5 @@ +class PostTemplate < Post + def self.post_type_id + PostType.mapping['PostTemplate'] + end +end diff --git a/app/models/post_type.rb b/app/models/post_type.rb index 7f3e7570b..aa6edee1f 100644 --- a/app/models/post_type.rb +++ b/app/models/post_type.rb @@ -19,6 +19,10 @@ def reactions end end + def templates + Post.undeleted.where(post_type_id: PostTemplate.post_type_id).where(template_post_type: self).to_a + end + def self.mapping Rails.cache.fetch 'network/post_types/post_type_ids', include_community: false do PostType.all.to_h { |pt| [pt.name, pt.id] } diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb index 064e2444d..aedf90433 100644 --- a/app/views/categories/_form.html.erb +++ b/app/views/categories/_form.html.erb @@ -141,7 +141,8 @@ <%= f.label :sequence, class: 'form-element' %> The order in which this category will appear in the header and on the category list page. Higher numbers - appear later. + appear later. Set to -1 to prevent the category from being listed. Note that users will still be able + to access it even when not listed; to change who can access it, change the minimum trust level instead. <%= f.number_field :sequence, class: 'form-element' %> diff --git a/app/views/post_history/post.html.erb b/app/views/post_history/post.html.erb index 8847e92e5..b82095af8 100644 --- a/app/views/post_history/post.html.erb +++ b/app/views/post_history/post.html.erb @@ -61,5 +61,10 @@ The detailed changes of this event are hidden because of a redaction.
<% end %> + <% if (event.before_template_post_type.present? || event.after_template_post_type.present?) && + event.before_template_post_type != event.after_template_post_type %> +