Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post Templates #1151

Open
wants to merge 28 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9ed3ffe
Implement creating and using post templates
MoshiKoi Aug 1, 2023
cfeebc9
Don't show template button if there's no templates
MoshiKoi Aug 1, 2023
7d3c0f2
Remove the debug log
MoshiKoi Aug 1, 2023
ec44526
Create a templates category
MoshiKoi Aug 1, 2023
fc01f4d
Remove the mod tool since the category exists now
MoshiKoi Aug 1, 2023
f058880
Fix a weird positioning bug
MoshiKoi Aug 2, 2023
d1d18ac
Only show non-deleted templates
MoshiKoi Aug 2, 2023
fa0e842
Add quick link to template post from preview
MoshiKoi Aug 2, 2023
7f3414f
Update app/assets/javascripts/posts.js
MoshiKoi Aug 4, 2023
c286056
Fix the tour
MoshiKoi Aug 2, 2023
fe600a4
Make implicit conversion explicit
MoshiKoi Aug 4, 2023
eef6757
Fix whitespace
MoshiKoi Aug 4, 2023
372242d
Add option to hide categories from the header
MoshiKoi Aug 6, 2023
37b3273
Add template association to Post model
MoshiKoi Aug 6, 2023
cc047ac
Fix the foreign key
MoshiKoi Aug 6, 2023
0f1af46
Make template_post_type optional
MoshiKoi Aug 13, 2023
e30da3c
Add diff when changing a template's post type
MoshiKoi Aug 13, 2023
5c29075
Merge branch 'develop' into templates
MoshiKoi Aug 15, 2023
e24ef2b
Fix markdown editor when the post is not a post
MoshiKoi Aug 15, 2023
52c64c8
Fix template_post_type in PostHistory
MoshiKoi Aug 15, 2023
ada2b8c
Rubocop
MoshiKoi Aug 15, 2023
b4c3dff
Insert into rather than replace post content
MoshiKoi Aug 20, 2023
24e0a58
Merge branch 'develop' into templates
Oaphi Sep 30, 2023
2fddcc5
Use -1 instead of null to hide categories
MoshiKoi Oct 12, 2023
56c239a
Fix disappearance of tools on non-posts
MoshiKoi Nov 11, 2023
a5cadcd
Merge branch 'develop' into templates
Oaphi Nov 11, 2023
3c7f82c
Merge branch 'develop' into templates
MoshiKoi Dec 30, 2023
658f2e1
Close the modal after choosing the template
MoshiKoi Dec 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/assets/javascripts/posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ const ALLOWED_ATTR = ['id', 'class', 'href', 'title', 'src', 'height', 'width',
'start', 'dir'];

$(() => {
$('.js-template').on('click', async ev => {
const $postField = $('.js-post-field');
$tgt = $(ev.target);
const content = $('#template-md-' + $tgt.attr('data-template-id')).val();
MoshiKoi marked this conversation as resolved.
Show resolved Hide resolved
$postField.val(content);
});

const $uploadForm = $('.js-upload-form');

const stringInsert = (str, idx, insert) => str.slice(0, idx) + insert + str.slice(idx);
Expand Down
1 change: 0 additions & 1 deletion app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ hr {
}

.modal {
position: fixed !important;
z-index: 8998;
}

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,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
Expand Down
2 changes: 1 addition & 1 deletion app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,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
Expand Down
6 changes: 6 additions & 0 deletions app/models/post_template.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class PostTemplate < Post
def self.post_type_id
PostType.mapping['PostTemplate']
end
end

4 changes: 4 additions & 0 deletions app/models/post_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ def reactions
end
end

def templates
Post.undeleted.where(post_type_id: PostTemplate.post_type_id).where(template_post_type_id: self).to_a
MoshiKoi marked this conversation as resolved.
Show resolved Hide resolved
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] }
Expand Down
11 changes: 9 additions & 2 deletions app/views/posts/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
</p>
<% end %>

<%= render 'shared/body_field', f: f, field_name: :body_markdown, field_label: t('posts.body_label'), post: post %>
<%= render 'shared/body_field', f: f, field_name: :body_markdown, field_label: t('posts.body_label'), post: post, post_type: post_type %>

<div class="post-preview"></div>

Expand All @@ -65,7 +65,7 @@
</div>
<div>
<span class="has-float-right has-font-size-caption js-character-count-post-title hide"
data-max="255" data-min="15" data-display-at="0.75">
data-max="255" data-min="<%= @category.min_title_length %>" data-display-at="0.75">
<i class="fas fa-ellipsis-h js-character-count__icon"></i>
<span class="js-character-count__count">0 / 255</span>
</span>
Expand Down Expand Up @@ -170,6 +170,13 @@
<% end %>
<% end %>

<% if post_type.id == PostTemplate.post_type_id %>
<div class="form-group">
<%= f.label :template_post_type_id, t('posts.template_post_type_label'), class: "form-element" %>
<%= f.select :template_post_type_id, options_for_select(PostType.all.map { |pt| [pt.name.underscore.humanize, pt.id] }), {}, { class: "form-element" } %>
</div>
<% end %>

<% if edit_comment %>
<hr/>
<div class="form-group">
Expand Down
2 changes: 1 addition & 1 deletion app/views/posts/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h1 class="has-margin-bottom-2">
New Post
New <%= @post_type.name.underscore.humanize.titleize %>
<% if @category.present? %>
in <%= @category.name %>
<% end %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/shared/_body_field.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
end[1]
%>
<% end %>
<%= render 'shared/markdown_tools' %>
<%= render 'shared/markdown_tools', post_type: post_type %>
<%= f.text_area field_name, **({ class: classes, rows: 15, placeholder: 'Start typing your post...' }).merge(value),
data: { character_count: ".js-character-count-post-body" } %>
<%= render 'posts/mdhint' %>
Expand Down
37 changes: 37 additions & 0 deletions app/views/shared/_markdown_tools.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,43 @@
</div>

<div class="markdown-tools widget--header js-markdown-tools">
<% templates = post_type.templates %>
<% if templates.any? %>
<div class="button-list is-gutterless">
<a href="javascript:void(0)" class="button is-outlined is-muted is-icon-only" data-drop="#templates"
data-drop-self-class-toggle="is-active" aria-label="Templates" title="Templates" role="button">
<i class="fas fa-copy"></i>
</a>
<div class="droppanel" id="templates">
<% templates.each do |template| %>
<a href="javascript:void(0)" class="js-template" aria-label="<%= template.title %>"
title="<%= template.title %>" role="button" data-template-id="<%= template.id %>">
<%= template.title %>
</a>
<a href="javascript:void(0)" data-modal="#template-<%= template.id %>"><i class="fas fa-fw fa-question-circle"></i></a>
<% end %>
</div>
<% templates.each do |template| %>
<div class="modal" id="template-<%= template.id %>">
<div class="modal--container">
<div class="modal--header">
<button class="button is-close-button modal--header-button" data-modal="#template-<%= template.id %>">&times;</button>
<%= link_to template.title, generic_share_link(template) %>
</div>
<div class="modal--body">
<textarea disabled id="template-md-<%= template.id %>"
class='form-element post-field widget--body h-b-0 h-m-0'><%= template.body_markdown %></textarea>
<%= sanitize(template.body) %>
</div>
<div class="modal--footer">
<a href="javascript:void(0)" class="js-template" aria-label="<%= template.title %>"
title="<%= template.title %>" role="button" data-template-id="<%= template.id %>">Apply</a>
</div>
</div>
</div>
<% end %>
</div>
<% end %>
<div class="button-list is-gutterless">
<%= md_button action: 'bold', label: 'Bold', class: 'is-icon-only' do %>
<i class="fas fa-fw fa-bold"></i>
Expand Down
2 changes: 2 additions & 0 deletions config/locales/strings/en.posts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ en:
Edit Comment
licence_label: >
License
template_post_type_label: >
For Post Type
unsaved_changes_confirmation: >
Any unsaved changes will be lost. Are you sure?
category_label: >
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20230801014134_add_template_post_type_to_posts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddTemplatePostTypeToPosts < ActiveRecord::Migration[7.0]
def change
add_reference :posts, :template_post_type, foreign_key: { to_table: :posts}
MoshiKoi marked this conversation as resolved.
Show resolved Hide resolved
end
end
14 changes: 10 additions & 4 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2023_06_13_205236) do
ActiveRecord::Schema[7.0].define(version: 2023_08_01_014134) do
create_table "abilities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.bigint "community_id"
t.string "name"
Expand Down Expand Up @@ -111,7 +111,9 @@
t.boolean "use_for_advertisement", default: true
t.integer "min_title_length", default: 15, null: false
t.integer "min_body_length", default: 30, null: false
t.bigint "default_filter_id"
t.index ["community_id"], name: "index_categories_on_community_id"
t.index ["default_filter_id"], name: "index_categories_on_default_filter_id"
t.index ["license_id"], name: "index_categories_on_license_id"
t.index ["sequence"], name: "index_categories_on_sequence"
t.index ["tag_set_id"], name: "index_categories_on_tag_set_id"
Expand Down Expand Up @@ -424,8 +426,8 @@
t.boolean "is_top_level", default: false, null: false
t.boolean "is_freely_editable", default: false, null: false
t.string "icon_name"
t.boolean "has_reactions"
t.bigint "answer_type_id"
t.boolean "has_reactions"
t.boolean "has_only_specific_reactions"
t.index ["answer_type_id"], name: "index_post_types_on_answer_type_id"
t.index ["name"], name: "index_post_types_on_name"
Expand Down Expand Up @@ -471,6 +473,7 @@
t.bigint "locked_by_id"
t.datetime "locked_at", precision: nil
t.datetime "locked_until", precision: nil
t.bigint "template_post_type_id"
t.index ["att_source"], name: "index_posts_on_att_source"
t.index ["body_markdown"], name: "index_posts_on_body_markdown", type: :fulltext
t.index ["category_id"], name: "index_posts_on_category_id"
Expand All @@ -488,6 +491,7 @@
t.index ["post_type_id"], name: "index_posts_on_post_type_id"
t.index ["score"], name: "index_posts_on_score"
t.index ["tags_cache"], name: "index_posts_on_tags_cache"
t.index ["template_post_type_id"], name: "index_posts_on_template_post_type_id"
t.index ["upvote_count"], name: "index_posts_on_upvote_count"
t.index ["user_id"], name: "index_posts_on_user_id"
end
Expand Down Expand Up @@ -754,15 +758,16 @@
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.boolean "read", default: false
t.index ["author_id"], name: "index_warnings_on_author_id"
t.index ["community_user_id"], name: "index_warnings_on_community_user_id"
t.index ["author_id"], name: "index_mod_messages_on_author_id"
t.index ["community_user_id"], name: "index_mod_messages_on_community_user_id"
end

add_foreign_key "abilities", "communities"
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "audit_logs", "communities"
add_foreign_key "audit_logs", "users"
add_foreign_key "categories", "filters", column: "default_filter_id"
add_foreign_key "categories", "licenses"
add_foreign_key "categories", "tag_sets"
add_foreign_key "category_filter_defaults", "categories"
Expand Down Expand Up @@ -796,6 +801,7 @@
add_foreign_key "posts", "communities"
add_foreign_key "posts", "licenses"
add_foreign_key "posts", "posts", column: "duplicate_post_id"
add_foreign_key "posts", "posts", column: "template_post_type_id"
add_foreign_key "posts", "users", column: "locked_by_id"
add_foreign_key "privileges", "communities"
add_foreign_key "site_settings", "communities"
Expand Down
18 changes: 17 additions & 1 deletion db/seeds/categories.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,20 @@
use_for_hot_posts: true
use_for_advertisement: false
color_code: bluegray
license_id: <%= License.unscoped.first.id %>
license_id: <%= License.unscoped.first.id %>

- name: Templates
short_wiki: Templates
# Default to moderators-only
min_trust_level: 4
min_title_length: 1
display_post_types:
- <%= PostType['PostTemplate'].id %>
post_type_ids:
- <%= PostType['PostTemplate'].id %>
tag_set_id: <%= TagSet.unscoped.where(name: 'Meta').first.id %>
use_for_hot_posts: false
use_for_advertisement: false
color_code: bluegray
# The PostTemplate actually has has_license: false, but just in case
license_id: <%= License.unscoped.where(name: 'CC0').first.id %>
15 changes: 15 additions & 0 deletions db/seeds/post_types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,19 @@
is_top_level: true
is_freely_editable: false
has_reactions: false
has_only_specific_reactions: false

- name: PostTemplate
description: ~
has_answers: false
has_votes: false
has_tags: false
has_parent: false
has_category: true
has_license: false
is_public_editable: false
is_closeable: false
is_top_level: true
is_freely_editable: false
has_reactions: false
has_only_specific_reactions: false