From 34c9723aa4a0ae42ff49c826b2c70bea60734343 Mon Sep 17 00:00:00 2001
From: ArtOfCode- <hello@artofcode.co.uk>
Date: Fri, 8 May 2020 14:27:06 +0100
Subject: [PATCH] Start on category required/topic tags

---
 app/assets/javascripts/categories.js          | 27 +++++++++++++++
 app/assets/javascripts/tags.js                | 25 ++++++++------
 app/controllers/categories_controller.rb      |  2 +-
 app/models/category.rb                        |  2 ++
 app/views/categories/_form.html.erb           | 34 ++++++++++++++++++-
 ...0508115752_add_category_tag_join_tables.rb | 13 +++++++
 6 files changed, 90 insertions(+), 13 deletions(-)
 create mode 100644 app/assets/javascripts/categories.js
 create mode 100644 db/migrate/20200508115752_add_category_tag_join_tables.rb

diff --git a/app/assets/javascripts/categories.js b/app/assets/javascripts/categories.js
new file mode 100644
index 000000000..8b766b11b
--- /dev/null
+++ b/app/assets/javascripts/categories.js
@@ -0,0 +1,27 @@
+$(() => {
+  $('.js-category-tag-set-select').on('change', ev => {
+    const $tgt = $(ev.target);
+    const tagSetId = $tgt.val();
+    const formGroups = $('.js-category-tags-group');
+    if (tagSetId) {
+      formGroups.each((i, el) => {
+        const $el = $(el);
+        const $caption = $el.find('.js-tags-group-caption');
+        $caption.find('[data-state="absent"]').hide();
+        $caption.find('[data-state="present"]').show();
+
+        $el.find('.js-tag-select').attr('data-tag-set', tagSetId);
+      });
+    }
+    else {
+      formGroups.each((i, el) => {
+        const $el = $(el);
+        const $caption = $el.find('.js-tags-group-caption');
+        $caption.find('[data-state="absent"]').show();
+        $caption.find('[data-state="present"]').hide();
+
+        $el.find('.js-tag-select').attr('data-tag-set', null);
+      });
+    }
+  });
+});
\ No newline at end of file
diff --git a/app/assets/javascripts/tags.js b/app/assets/javascripts/tags.js
index 1439c371f..3b07c93a3 100644
--- a/app/assets/javascripts/tags.js
+++ b/app/assets/javascripts/tags.js
@@ -1,14 +1,17 @@
 $(() => {
-  $('.js-tag-select').select2({
-    tags: true,
-    ajax: {
-      url: '/tags',
-      data: function (params) {
-        return Object.assign(params, { tag_set: $(this).data('tag-set') });
-      },
-      headers: { 'Accept': 'application/json' },
-      delay: 100,
-      processResults: data => ({results: data.map(t => ({id: t.name, text: t.name}))}),
-    }
+  $('.js-tag-select').each((i, el) => {
+    const $tgt = $(el);
+    $tgt.select2({
+      tags: $tgt.attr('data-create') !== 'false',
+      ajax: {
+        url: '/tags',
+        data: function (params) {
+          return Object.assign(params, { tag_set: $(this).data('tag-set') });
+        },
+        headers: { 'Accept': 'application/json' },
+        delay: 100,
+        processResults: data => ({results: data.map(t => ({id: t.name, text: t.name}))}),
+      }
+    });
   });
 });
\ No newline at end of file
diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb
index e1bd54c0f..62b0a6329 100644
--- a/app/controllers/categories_controller.rb
+++ b/app/controllers/categories_controller.rb
@@ -75,7 +75,7 @@ class CategoriesController < ApplicationController
   def category_params
     params.require(:category).permit(:name, :short_wiki, :tag_set_id, :is_homepage, :min_trust_level, :button_text,
                                      :color_code, :min_view_trust_level, :license_id, :sequence, display_post_types: [],
-                                     post_type_ids: [])
+                                     post_type_ids: [], required_tag_ids: [], topic_tag_ids: [])
   end
 
   def verify_view_access
diff --git a/app/models/category.rb b/app/models/category.rb
index 486fcb87c..cba36d5c3 100644
--- a/app/models/category.rb
+++ b/app/models/category.rb
@@ -2,6 +2,8 @@ class Category < ApplicationRecord
   include CommunityRelated
 
   has_and_belongs_to_many :post_types
+  has_and_belongs_to_many :required_tags, class_name: 'Tag', join_table: 'categories_required_tags'
+  has_and_belongs_to_many :topic_tags, class_name: 'Tag', join_table: 'categories_topic_tags'
   has_many :posts
   belongs_to :tag_set
   belongs_to :license
diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb
index 9613e9d0c..95a830f61 100644
--- a/app/views/categories/_form.html.erb
+++ b/app/views/categories/_form.html.erb
@@ -31,7 +31,7 @@
     <%= f.label :tag_set_id, 'Tag set', class: 'form-element' %>
     <span class="form-caption">Which tag set may posts in this category draw from?</span>
     <%= f.select :tag_set_id, options_for_select(TagSet.all.map { |ts|  [ts.name, ts.id] }, selected: @category.tag_set_id),
-                 { include_blank: true }, class: 'form-element' %>
+                 { include_blank: true }, class: 'form-element js-category-tag-set-select' %>
   </div>
 
   <div class="form-group">
@@ -90,5 +90,37 @@
     <%= f.number_field :sequence, class: 'form-element' %>
   </div>
 
+  <div class="form-group js-category-tags-group">
+    <%= f.label :required_tag_ids, 'Required tags', class: 'form-element' %>
+    <span class="form-caption js-tags-group-caption">
+      <span data-state="present" style="<%= @category.tag_set.nil? ? 'display: none' : '' %>">
+        Required tags for this category - every post will be required to have one of these tags.
+      </span>
+      <span data-state="absent" style="<%= @category.tag_set.nil? ? '' : 'display: none' %>">
+        Select a tag set first.
+      </span>
+    </span>
+    <%= f.select :required_tag_ids, options_for_select(@category.required_tags.map { |t| [t.name, t.id] },
+                                                       selected: @category.required_tags.pluck(:name)),
+                 { include_blank: true }, multiple: true, class: 'form-element js-tag-select',
+                 data: { tag_set: @category.tag_set&.id, create: 'false' } %>
+  </div>
+
+  <div class="form-group js-category-tags-group">
+    <%= f.label :required_tag_ids, 'Topic tags', class: 'form-element' %>
+    <span class="form-caption js-tags-group-caption">
+      <span data-state="present" style="<%= @category.tag_set.nil? ? 'display: none' : '' %>">
+        Tags that will be highlighted as the most important tag on a question.
+      </span>
+      <span data-state="absent" style="<%= @category.tag_set.nil? ? '' : 'display: none' %>">
+        Select a tag set first.
+      </span>
+    </span>
+    <%= f.select :topic_tag_ids, options_for_select(@category.topic_tags.map { |t| [t.name, t.id] },
+                                                       selected: @category.topic_tags.pluck(:name)),
+                 { include_blank: true }, multiple: true, class: 'form-element js-tag-select',
+                 data: { tag_set: @category.tag_set&.id, create: 'false' } %>
+  </div>
+
   <%= f.submit 'Save', class: 'button is-filled' %>
 <% end %>
diff --git a/db/migrate/20200508115752_add_category_tag_join_tables.rb b/db/migrate/20200508115752_add_category_tag_join_tables.rb
new file mode 100644
index 000000000..f79752d7c
--- /dev/null
+++ b/db/migrate/20200508115752_add_category_tag_join_tables.rb
@@ -0,0 +1,13 @@
+class AddCategoryTagJoinTables < ActiveRecord::Migration[5.2]
+  def change
+    create_table :categories_required_tags, id: false, primary_key: [:category_id, :tag_id] do |t|
+      t.bigint :category_id
+      t.bigint :tag_id
+    end
+
+    create_table :categories_topic_tags, id: false, primary_key: [:category_id, :tag_id] do |t|
+      t.bigint :category_id
+      t.bigint :tag_id
+    end
+  end
+end
-- 
GitLab