FEATURE: tag group options: limit usage of one tag per group, tags in a group can't be used unless a prerequisite tag is used

This commit is contained in:
Neil Lalonde
2016-06-09 16:00:19 -04:00
parent 171dbd4b09
commit a6090339a7
14 changed files with 243 additions and 41 deletions

View File

@@ -36,12 +36,19 @@ export default Ember.TextField.extend({
const site = this.site,
self = this,
filterRegexp = new RegExp(this.site.tags_filter_regexp, "g");
var limit = this.siteSettings.max_tags_per_topic;
if (this.get('unlimitedTagCount')) {
limit = null;
} else if (this.get('limit')) {
limit = parseInt(this.get('limit'));
}
this.$().select2({
tags: true,
placeholder: I18n.t(this.get('placeholderKey') || 'tagging.choose_for_topic'),
maximumInputLength: this.siteSettings.max_tag_length,
maximumSelectionSize: self.get('unlimitedTagCount') ? null : this.siteSettings.max_tags_per_topic,
maximumSelectionSize: limit,
initSelection(element, callback) {
const data = [];
@@ -92,7 +99,12 @@ export default Ember.TextField.extend({
url: Discourse.getURL("/tags/filter/search"),
dataType: 'json',
data: function (term) {
const d = { q: term, limit: self.siteSettings.max_tag_search_results, categoryId: self.get('categoryId') };
const d = {
q: term,
limit: self.siteSettings.max_tag_search_results,
categoryId: self.get('categoryId'),
selected_tags: self.get('tags')
};
if (!self.get('everyTag')) {
d.filterForInput = true;
}

View File

@@ -20,7 +20,9 @@ const TagGroup = RestModel.extend({
return Discourse.ajax(url, {
data: {
name: this.get('name'),
tag_names: this.get('tag_names')
tag_names: this.get('tag_names'),
parent_tag_name: this.get('parent_tag_name') ? this.get('parent_tag_name') : undefined,
one_per_topic: this.get('one_per_topic')
},
type: this.get('id') ? 'PUT' : 'POST'
}).then(function(result) {

View File

@@ -1,13 +1,25 @@
<div class="tag-group-content">
<h1>{{text-field value=model.name}}</h1>
<br/>
<div class="group-tags-list">
<label>{{i18n 'tagging.groups.tags_label'}}</label>
<br/>
{{tag-chooser tags=model.tag_names everyTag="false" unlimitedTagCount="true"}}
</div>
<br/>
<section class="group-tags-list">
<label>{{i18n 'tagging.groups.tags_label'}}</label><br/>
{{tag-chooser tags=model.tag_names everyTag="true" unlimitedTagCount="true"}}
</section>
<section class="parent-tag-section">
<label>{{i18n 'tagging.groups.parent_tag_label'}}</label>
{{tag-chooser tags=model.parent_tag_name everyTag="true" limit="1" placeholderKey="tagging.groups.parent_tag_placeholder"}}
<span class="description">{{i18n 'tagging.groups.parent_tag_description'}}</span>
</section>
<section class="group-one-per-topic">
<label>
{{input type="checkbox" checked=model.one_per_topic name="onepertopic"}}
{{i18n 'tagging.groups.one_per_topic_label'}}
</label>
</section>
<button {{action "save"}} disabled={{model.disableSave}} class='btn'>{{i18n 'tagging.groups.save'}}</button>
<button {{action "destroy"}} class='btn btn-danger'><i class="fa fa-trash-o"></i> {{i18n 'tagging.groups.delete'}}</button>
<button {{action "destroy"}} disabled={{model.disableSave}} class='btn btn-danger'><i class="fa fa-trash-o"></i> {{i18n 'tagging.groups.delete'}}</button>
<span class="saving {{unless model.savingStatus 'hidden'}}">{{model.savingStatus}}</span>
</div>

View File

@@ -222,6 +222,14 @@ header .discourse-tag {color: $tag-color !important; }
.tag-group-content {
width: 75%;
float: right;
section {
margin-bottom: 20px;
}
label {
font-size: 1em;
display: inline-block;
margin-right: 10px;
}
}
.group-tags-list .tag-chooser {
height: 150px !important;
@@ -233,4 +241,10 @@ header .discourse-tag {color: $tag-color !important; }
.saving {
margin-left: 20px;
}
.parent-tag-section {
.tag-chooser {
width: 200px;
margin-right: 10px;
}
}
}

View File

@@ -69,7 +69,10 @@ class TagGroupsController < ApplicationController
end
def tag_groups_params
params[:tag_names] ||= []
params.permit(:id, :name, :tag_names => [])
result = params.permit(:id, :name, :one_per_topic, :tag_names => [], :parent_tag_name => [])
result[:tag_names] ||= []
result[:parent_tag_name] ||= []
result[:one_per_topic] = (params[:one_per_topic] == "true")
result
end
end

View File

@@ -117,7 +117,12 @@ class TagsController < ::ApplicationController
tags_with_counts = DiscourseTagging.filter_allowed_tags(
self.class.tags_by_count(guardian, params.slice(:limit)),
guardian,
{ for_input: params[:filterForInput], term: params[:q], category: category }
{
for_input: params[:filterForInput],
term: params[:q],
category: category,
selected_tags: params[:selected_tags]
}
)
tags = tags_with_counts.count.map {|t, c| { id: t, text: t, count: c } }
@@ -125,7 +130,7 @@ class TagsController < ::ApplicationController
unused_tags = DiscourseTagging.filter_allowed_tags(
Tag.where(topic_count: 0),
guardian,
{ for_input: params[:filterForInput], term: params[:q], category: category }
{ for_input: params[:filterForInput], term: params[:q], category: category, selected_tags: params[:selected_tags] }
)
unused_tags.each do |t|

View File

@@ -6,7 +6,19 @@ class TagGroup < ActiveRecord::Base
has_many :category_tag_groups, dependent: :destroy
has_many :categories, through: :category_tag_groups
belongs_to :parent_tag, class_name: 'Tag'
def tag_names=(tag_names_arg)
DiscourseTagging.add_or_create_tags_by_name(self, tag_names_arg)
end
def parent_tag_name=(tag_names_arg)
if tag_names_arg.empty?
self.parent_tag = nil
else
if tag_name = DiscourseTagging.tags_for_saving(tag_names_arg, Guardian.new(Discourse.system_user)).first
self.parent_tag = Tag.find_by_name(tag_name) || Tag.create(name: tag_name)
end
end
end
end

View File

@@ -1,4 +1,4 @@
class TagGroupMembership < ActiveRecord::Base
belongs_to :tag
belongs_to :tag_group, counter_cache: "tag_count"
belongs_to :tag_group, counter_cache: "tag_count" # TODO: remove counter cache
end

View File

@@ -1,7 +1,11 @@
class TagGroupSerializer < ApplicationSerializer
attributes :id, :name, :tag_names
attributes :id, :name, :tag_names, :parent_tag_name, :one_per_topic
def tag_names
object.tags.pluck(:name).sort
end
def parent_tag_name
[object.parent_tag.try(:name)].compact
end
end