Enable tagging only in some categories

This is looking good @neil. One thing that would be good relating to this would be the simple option to ‘enable tags in category’ option in the category modal.

In my use case I only want tags (and specific tags at that) to be able to be used in specific categories. E.g. in those categories where I don’t want tags enabled I wouldn’t want the tag input field to be shown to users. Is this doable?

4 个赞

It’s probably doable, but I have to focus on completing some other tag features first. Will have to come back around to this one later.

9 个赞

I would love to only enable tags in certain categories as well - bookmarking this thread to keep an eye on the discussion moving forward

I think this is currently possible in the way that you can define tag-groups and you can configure category setting in order to use that tag-group.

do you mean something else?

3 个赞

Another feature that would make sense related to this:

If tag filter is enabled, yet only certain categories have tags availble using the ‘Tags that can only be used in this category’ in category settings, I believe the homepage (both the main category, latest and top) pages should have the tag filter disabled by default.

I.e. only when digging down into the categories/sub-categories with tags allowed should the tag filter be shown (showing the respective tags available).

Otherwise from the homepage (whether that be categories or latest), you’ll get a whole bunch of tags in the filter, often without context as they only have context when filtered inside their respective categories.

Does this make sense?

1 个赞

Keen to test this out. Am I able to grab some code somewhere for this? Cheers.

完全同意。在我们的示例中,我们有一个带有专用标签组的纪录片版块。我希望在此处显示标签下拉菜单,且仅包含专用标签。目前这已经可以正常工作。

但我不希望顶级“最新”或“全部类别热门”的下拉菜单中出现相同的标签。依我看,这削弱了为特定类别分配专用标签组的优势,并且在顶级页面会造成混淆。

只有未分配给任何类别标签组的全局标签,才应显示在顶级标签下拉菜单中。

在标签组设置中,应包含类似选项:

[ ] 仅将标签组限制在已分配的分类中,不在顶级下拉菜单中显示

1 个赞

这也是我希望能看到的功能。

在我第一个(导入的)论坛上,我需要“分类广告”类别。

由于 Discourse 不像 vbulletin 或 phpbb 等其他引擎那样有包含类别的“文件夹”,我当时基本上只有三个选择:

  1. 创建一个单一的“广告”类别,同时用于“出售”和“求购”帖子,让用户自己在主题标题前添加 [BUY] 或 [SELL] 前缀(所以会有 2000 多个主题……)
  2. 创建一个单一的“广告”类别,让用户使用“buy”或“sell”标签。这显然最方便,但我们在其他任何类别中都不使用标签,而且用户会在所有类别的编辑器中看到标签字段,这会造成困惑。
  3. 在顶层创建两个“广告”类别:“出售”和“求购”。这是我们最终做出的选择;

现在我正在导入另一个更大的论坛,遇到了完全相同的“问题”,只不过这次我需要为两个类别使用标签:一个是“分类广告”类别,另一个是“其他语言”类别,该类别仅包含用外语撰写的帖子,这些帖子需要使用特定标签来标识其语言,例如“hebrew”、“danish”等。

同样,我们在其他任何类别中都不需要标签。

我需要在这两个类别的主题列表导航栏中显示标签选择器,但在其他类别中不需要。

我可以用一点 CSS 轻松地在需要时隐藏它,但主要问题是编辑器中的标签输入框,无法随意显示或隐藏……

我想在这个阶段,最好的方法是覆盖编辑器的 tagValidation 方法。
每当在编辑器中选择一个类别时,根据所选类别隐藏或显示标签输入框。

当标签字段被隐藏时,看起来会是这样,留有一个空白区域:

此外,如果我们使用具有自定义编辑器字段的插件或主题组件(例如 location plugin),这可能会破坏布局。

我正在尝试使用我构思的变通方法。

使用 CSS 在主题列表中隐藏标签选择器:


(您必须使用 CSS 选择器针对每个可打标签的分类)

body:not(.category-other-languages):not(.category-trading-post) {
    .category-breadcrumb .tag-drop {
        display: none;
    }
}

使用 JS 在编辑器中显示和隐藏标签选择器:

<script type="text/discourse-plugin" version="0.8.23">
    // 仅在必要时显示编辑器中的标签选择器
    const discourseComputed = require("discourse-common/utils/decorators").default;
    const EmberObject = require("@ember/object").default;
    function toggleTagChooser(display = "hide") {
        if (display == "show") {
            document.getElementsByClassName("mini-tag-chooser")[0].style.display = "block";
            document.getElementsByClassName("reply-area")[0].classList.add("with-tags");
            return;
        }
        // 验证标签选择器的存在
        let tagChoser = document.getElementsByClassName("mini-tag-chooser");
        if(tagChoser.length > 0) {
            tagChoser[0].style.display = "none";
            document.getElementsByClassName("reply-area")[0].classList.remove("with-tags");
        }
        return;
    }
    api.modifyClass('controller:composer', {
        @discourseComputed("model.category", "model.tags", "lastValidatedAt")
        tagValidation(category, tags, lastValidatedAt) {
            // 切换标签选择器的自定义代码
            toggleTagChooser("hide");
            if(category != null) {
                if (
                    category.allow_global_tags == true ||
                    category.allowed_tag_groups.length > 0 ||
                    category.allowed_tags.length > 0
                ) {
                    toggleTagChooser("show");
                }
            }
            // 自定义代码结束
            const tagsArray = tags || [];
            if (this.site.can_tag_topics && !this.currentUser.staff && category) {
                // category.minimumRequiredTags 同时包含 minimum_required_tags 和 required_tag_groups
                if (category.minimumRequiredTags > tagsArray.length) {
                    return EmberObject.create({
                        failed: true,
                        reason: I18n.t("composer.error.tags_missing", {
                            count: category.minimumRequiredTags,
                        }),
                        lastShownAt: lastValidatedAt,
                    });
                }
            }
        }
    });
</script>
1 个赞

这正是我想要的。太好了。

在当前的核心代码中,当某个类别下用户没有可选标签时,仍显示标签选择框,这是特别错误的。最后的代码解决了这个用户体验问题。核心代码应该以这种方式实现 @team

此外,标签选择下拉菜单应包含两个标准文本:

“可选标签”

以及当某个类别的标签对用户为必填(且可用)时的文本:

“至少选择 X 个标签”

1 个赞

通过创建标签组,您可以强制要求某个分类下的所有帖子必须使用一组标签(如“买入”或“卖出”)中的一个。

1 个赞

标签选择框仍会显示,即使对于具有强制标签组的类别,其编辑器中仍显示“可选标签”;而在其他类别中,当用户没有任何可用标签时,该框也会显示。从用户体验角度来看,这非常令人困惑。用户必须点击错误弹窗,才能明白所需的内容。

1 个赞

我明白,我只是想以某种方式隐藏那些不支持标签的类别的标签功能,正如 @Terrapop 所解释的那样。

当在站点设置中禁用标签时,类别选择器与主题标题位于同一行:

使用我的变通方案,会稍微浪费一些空间,因为类别选择器始终位于主题标题下方:

一方面,根据是否需要标签来动态调整类别选择器的位置可能不符合良好的用户体验设计。另一方面,我们很少多次使用类别选择器。

1 个赞

我对空间浪费倒不太担心,但发现了你那段非常不错的 JS 代码中的另一个“问题”。或许你能帮忙看看?

我们有一些“仅员工可见”的标签组(例如隐藏标签和系统标签),以及按类别为用户设置的强制标签组。两者都通过“将这些标签组限制在此类别中”进行关联。

现在,这段代码仅检查类别是否允许标签,或 tag_groups.length > 0,或 allowed_tags > 0。但不幸的是,由于受限标签组中也包含了那些仅员工可见的标签组,这些条件总是成立的。

能否修改代码以考虑用户上下文,并判断该特定用户是否真的有可用的标签?

if(category != null) {
    if (
        category.allow_global_tags == true ||
        category.allowed_tag_groups.length > 0 ||
        category.allowed_tags.length > 0
    ) {
        toggleTagChooser("visible");
    }
}

是否可能针对非员工用户,仅统计 category.allowed_tag_groups 数组中的公开标签组?(或者该数组中是否仅包含名称而未包含状态?)

public_category.allowed_tag_groups = [public_tag_group.name, staff_only_tag_group.name]
private_category.allowed_tag_groups = [private_tag_group.name, staff_only_tag_group.name]

好的,更新如下:

在我们的案例中,我们将检查 allowed_tag_groups 中的名称,并在当前用户不是员工时将其从数组中排除。但这只是一个临时的变通方案,因为我不确定如何在此处添加用户上下文(或者考虑到当前的核心代码,这是否可行,我觉得不太可能)。

var non_staff_tag_groups = category.allowed_tag_groups.filter(filterHidden);
function filterHidden(value) {
  if(value.toLowerCase().indexOf("hidden") === -1 && value.toLowerCase().indexOf("system") === -1) return value;
}
if (
    category.allow_global_tags == true ||
    (category.allowed_tag_groups.length > 0 && this.currentUser.staff) ||
    (non_staff_tag_groups.length > 0 && !this.currentUser.staff) ||
    category.allowed_tags.length > 0
) {
    toggleTagChooser("visible");
}

但这仍然是一个临时的 hack。整个作曲器中的标签下拉菜单应该通过核心功能实现更丰富的上下文感知,并涵盖上述所有情况。

2 个赞

抱歉,我好像在 2020 年没有看到您的消息!

不过,我的代码在最近一次 Discourse 更新后损坏了。这是一个有效的更新(CSS 没有改变):

定位您想要隐藏标签选择器的类别类:

body:not(.category-other-languages):not(.category-trading-post) {
    .category-breadcrumb .tag-drop {
        display: none;
    }
}

将动态切换标签选择器的脚本:


    // 仅在必要时显示撰写器中的标签选择器
    const discourseComputed = require("discourse-common/utils/decorators").default;
    const EmberObject = require("@ember/object").default;
    function toggleTagChooser(display = "hide") {
        if (display == "show") {
            document.getElementsByClassName("mini-tag-chooser")[0].style.display = "block";
            document.getElementsByClassName("reply-area")[0].classList.add("with-tags");
            return;
        }
        // 验证标签选择器的存在
        let tagChoser = document.getElementsByClassName("mini-tag-chooser");
        if(tagChoser.length > 0) {
            tagChoser[0].style.display = "none";
            document.getElementsByClassName("reply-area")[0].classList.remove("with-tags");
        }
        return;
    }
    api.modifyClass('controller:composer', {
        @discourseComputed("model.category", "model.tags", "lastValidatedAt")
        tagValidation(category, tags, lastValidatedAt) {
            // 自定义代码以切换标签选择器
            toggleTagChooser("hide");
            if(category != null) {
                if (
                    category.allow_global_tags == true ||
                    category.allowed_tag_groups.length > 0 ||
                    category.allowed_tags.length > 0
                ) {
                    toggleTagChooser("show");
                }
            }
            // 自定义代码结束
            const tagsArray = tags || [];
            if (this.site.can_tag_topics && !this.currentUser.staff && category) {
                // category.minimumRequiredTags 包含 minimum_required_tags 和 required_tag_groups
                if (category.minimumRequiredTags > tagsArray.length) {
                    return EmberObject.create({
                        failed: true,
                        reason: I18n.t("composer.error.tags_missing", {
                            count: category.minimumRequiredTags,
                        }),
                        lastShownAt: lastValidatedAt,
                    });
                }
            }
        }
    });

关于那个……都过去 6 年了,老兄 :sweat_smile:

我认为现在的标签组功能可以提供接近的体验。
您可以将一个标签组绑定到多个类别,然后禁止创建新标签。
不确定在这里是否需要#pr-welcome,我将移除它,期望的更改需要被正确指定。这大概是要求在类别设置中添加一个复选框,但即使是这样也需要仔细考虑,它是默认勾选的吗?额外的设置是否会让很多人感到困惑?