您好,
当从 /g 页面访问群组时,是否有办法让群组 URL 指向 /g/group-slug/messages 而不是 /g/group-slug/members?
我们有几个群组用于群组消息。让人们少点击一次即可到达他们群组的消息将很有帮助。这比查看群组成员对我们来说更重要。
我知道可以通过直接链接来做到这一点,但我希望它来自 /g?type=my 页面,该页面非常动态且以用户为中心。
您好,
当从 /g 页面访问群组时,是否有办法让群组 URL 指向 /g/group-slug/messages 而不是 /g/group-slug/members?
我们有几个群组用于群组消息。让人们少点击一次即可到达他们群组的消息将很有帮助。这比查看群组成员对我们来说更重要。
我知道可以通过直接链接来做到这一点,但我希望它来自 /g?type=my 页面,该页面非常动态且以用户为中心。
它们不是常规链接。它们是通过 link-to Ember 组件处理的,并且涉及到一些路由。
最简单的方法是劫持该元素的点击事件并在那里执行你的操作。这会放在主题的 common > header 中。
<script
type="text/x-handlebars"
data-template-name="/connectors/group-index-box-after/link-to-group-inbox"></script>
<script type="text/discourse-plugin" version="0.8">
const DiscourseURL = require("discourse/lib/url").default;
api.registerConnectorClass('group-index-box-after', 'link-to-group-inbox', {
setupComponent(args) {
const group = args.model;
if (group.is_group_user && group.has_messages) {
const groupLink = document.querySelector(`.group-box.${group.name}`);
const newHref = `/g/${group.name}/messages`;
// 更新浏览器标题并处理新标签页
groupLink.href = newHref;
// 重定向链接
groupLink.addEventListener("click", (event) => {
DiscourseURL.routeTo(newHref);
event.preventDefault();
}, {once: true})
}
}
});
</script>
如果用户是该组成员并且该组有消息,它将重定向到收件箱。否则,它将回退到默认的 /members 页面。
太棒了——这太神奇了!!!!它效果很好。谢谢。
稍后……
抱歉,我遇到了一个后续问题,需要您提供一点帮助!
我的几个群组仍然显示 /g/group-slug/messages,尽管它们没有任何消息。
仔细检查后,它们过去曾有过消息,这些消息已被转换为主题或删除。Data Explorer 显示这些群组在 Groups 表中 has_messages 为 True。
我尝试通过 Rails 为这些群组更改它,但似乎无法实现:
[2] pry(main)> Group.find_by_name(“group-slug”).has_messages
=> true
[3] pry(main)> Group.find_by_name(“group-slug”).has_messages = false
=> false
[4] pry(main)> Group.find_by_name(“group-slug”).has_messages
=> true
有什么建议吗?除了删除群组并重新创建(我不太愿意这样做)之外。
您只需要在 rails 控制台中运行此行。它应该会更新所有组。
Group.refresh_has_messages!
这对我来说都奏效了,除了两个——谢谢。最后这两个顽固的,我想我只能删除并重新创建了!
在这样做的时候,我发现了原因——这是一个小小的 #bug。
在将群组私信转换为主题时,会保留被邀请者的信息。虽然如果主题被转换回来,这会很好,但它确实意味着在运行 Group.refresh_has_messages! 时,他们会被错误地计算在内。
是否也可以劫持点击@提及的组后,再点击进入组所获得的链接?我认为这是不使用URL就能访问组的仅有的两种方式。
我现在想要的是(是不是很贪心?),让所有指向组的链接都像你的代码处理/g页面链接那样。
@Johani,这可以做到吗?我研究了一下,这显然远远超出了我的能力范围。
当然,您可以在主题/组件的 header 标签中尝试类似以下的代码。我留下了一些注释,如果您想跟随。准备好使用时可以删除它们。
同样的应用规则。如果用户是组成员并且该组有消息,Discourse 将导航到组收件箱。否则,用户将进入成员目录。
<script type="text/discourse-plugin" version="0.8">
// Part 1: modify the path for the links in the group cards. This ensure that the link
// title reflects where it leads and handles opening the link a new tab.
const discourseComputed = require("discourse-common/utils/decorators").default;
api.modifyClass("component:group-card-contents", {
// The groupPath property is used to generate the href for the group links
// in the group card. Let's modify it
@discourseComputed("group")
groupPath(group) {
// get the default value from core
let groupURL = this._super(...arguments);
// if the user matches our requirment, modify the url so it goes to the inbox
if (group.is_group_user && group.has_messages) {
groupURL = `${groupURL}/messages/`;
}
// return either the default or modified value
return groupURL;
}
});
// Part 2: modify in-app routing. This ensures that regular in-app navigation is
// handled correctly and takes the user to the group inbox if they meet the
// requirements
const DiscourseURL = require("discourse/lib/url").default;
const { groupPath } = require("discourse/lib/url");
const { action } = require("@ember/object");
api.modifyClass("controller:user-card", {
// showGroup here is an action that belongs to the user-card controller.
// This is what gets called when you click on the group name / avatar inside group cards
@action
showGroup(group) {
// call super to make sure code from core is loaded first
this._super(...arguments);
// group path is a built-in Discourse url helper function
let groupURL = groupPath(group.name);
// if the user matches the requirments, modify the url
if (group.is_group_user && group.has_messages) {
groupURL = `${groupURL}/messages/`;
}
// call routeTo() with either the default or the modified groupURL
DiscourseURL.routeTo(groupURL);
}
});
</script>
你太棒了!它适用于任何使用卡片的情况。
现在只有一种类型的链接仍然是无向的:当在群组私人消息中时,群组的链接。从群组消息导航到群组(以及收件箱)时,这实际上非常方便。
你认为我们也能抓住它吗?
(顺便说一句,一旦我们完成,我会将其打包成一个 TC 并为此创建一个主题,以便其他人可以轻松访问)
这些链接使用了略有不同的序列化器——因为在那里不需要所有的组数据。
不过,您可以在初始页面视图中存储当前用户群组的过滤列表,并将其用作检查成员资格的参考。这些信息已包含在初始负载中,因此不会产生额外请求等开销。类似这样:
<script type="text/discourse-plugin" version="0.8">
const user = api.getCurrentUser();
if (!user) {
return;
}
const userGroups = user.groups.map(group => group.name);
api.reopenWidget("pm-map-user-group", {
transform(attrs) {
const group = attrs.group;
const isGroupUser = Object.values(userGroups).includes(group.name);
// {href: "/g/foo"};
let groupURL = this._super(...arguments);
if (isGroupUser && group.has_messages) {
groupURL.href = `${groupURL.href}/messages/`;
}
return groupURL;
}
});
</script>
将此代码段保留在其自己的脚本标签中,并将其添加到标题中,与其他代码段一起。您将其分开是因为如果用户未登录,它会快速退出。
我们到了!效果非常好,在手机上也能用。
感谢Joe的惊人坚持。我最好履行我的承诺,开始着手开发那个#theme-component,对吧?
稍后……
来了:
我还有一件事需要帮助才能完全完成。我知道这有点厚脸皮。
我现在正尝试修改 Pavilion JavaScript,就是无法让它正常工作。这是我尝试修改的内容:
createWidget('layouts-group-link', {
tagName: 'li.layouts-group-link',
buildKey: (attrs) => `layouts-group-link-${attrs.id}`,
getGroupTitle(group) {
return h('span.group-title', group.name);
},
isOwner(group) {
if (group.owner) {
return h('span.group-owner-icon', iconNode('shield-alt'));
}
},
html(attrs) {
const contents = [this.getGroupTitle(attrs), this.isOwner(attrs)];
return contents;
},
click() {
DiscourseURL.routeTo(`/g/${this.attrs.name}/messages`);
},
});
我该如何将其应用到最后一段 click(){etc} 中?我已经尝试了我能想到的一切,但都失败了。我最终只会完全破坏链接。
if (group.is_group_user && group.has_messages) {
groupURL = `${groupURL}/messages/`;
}
没关系!!!@keegan 已经解决了:
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
对于一些存在“消息幽灵”的群组,这不起作用。可以通过以下查询来识别这些群组(前提是群组互动设置中已限制消息传递):
SELECT id, name, has_messages, messageable_level
From groups
Where messageable_level < 10
AND messageable_level <> 3
AND has_messages = true
ORDER by id
你也可以通过修改 groups 表来强制重置(当然是在 Rails 控制台中,请先备份!)。
Group.where(id: XXX).update_all(has_messages: false)
如果这不起作用或恢复了,你可能还需要清理 topic_groups 和 topic_allowed_groups 表:
TopicGroup.where(group_id: XXX).destroy_all
TopicAllowedGroup.where(group_id: XXX).destroy_all
此主题已在 30 天后自动关闭。不再允许回复。