SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 04:52
1
在一天结束时,我需要在 discourse 主题列表正文中添加一个新的主题按钮。每个工程师都在抱怨他们不喜欢“开始新对话”按钮只在每个类别的主题列表底部。他们不想使用顶部的“新主题”菜单选项,因为这不会在他们当前所在的类别中启动主题。
我已经通过 llama 3.1 405B 和 gpt4(通过 ask.discourse.com )运行了此代码,但无法获得可以编译的 JavaScript 版本。我一直收到编译错误:SyntaxError: Private field must be used in an enclosing class。
我还收到一个 widget 注册表错误,但这是因为自定义 widget 由于 js 编译错误而从未被创建。
我正在使用 Discourse Central Theme。
给定这个 Header 部分:
“<script type="text/discourse-plugin" version="0.8.18">
api.createWidget('custom-new-topic-button', {
tagName: 'div.custom-new-topic-button',
buildKey: () => `custom-new-topic-button`,
html() {
return [
this.attach('button', {
className: 'btn btn-primary',
action: 'createNewTopic',
contents: 'New Topic'
})
];
},
click() {
const composerController = this.container.lookup("controller:composer");
const currentCategory = this.container.lookup("controller:navigation/category").get("model.id");
composerController.open({
action: require("discourse/models/composer").default.CREATE_TOPIC,
draftKey: require("discourse/models/composer").default.DRAFT,
categoryId: currentCategory,
});
return false;
},
});
api.decorateWidget('topic-list:before', (helper) => {
if (api.getCurrentUser()) {
helper.appendChild(helper.createWidget('custom-new-topic-button'));
}
});
</script>
”
这个 Head 部分
<script>
{{#if currentUser}}
<div>
{{custom-new-topic-button}}
</div>
{{/if}}
</script>
和这个 CSS
.topic-list-body::before {
content: "";
display: block;
position: relative; /* Important to allow absolute positioning within */
}
.topic-list-body-new-topic {
position: absolute;
top: 0;
left: 0;
padding: 10px;
background: #f2f3f5;
border-bottom: 1px solid #ccc;
}
.custom-new-topic-button .btn.btn-primary {
background-color: #007bff;
border-color: #007bff;
color: #fff;
}
这是我原来的代码,最新的建议是
<script type="text/discourse-plugin" version="0.8.18">
api.createWidget('custom-new-topic-button', {
tagName: 'div.custom-new-topic-button',
buildKey() {
return 'custom-new-topic-button';
},
defaultState() {
return {};
},
html() {
return [
this.attach('button', {
className: 'btn btn-primary',
action: 'createNewTopic',
contents: 'New Topic'
})
];
},
createNewTopic() {
const composerController = this.container.lookup("controller:composer");
const currentCategory = this.container.lookup("controller:navigation/category").get("model.id");
const Composer = require("discourse/models/composer").default;
composerController.open({
action: Composer.CREATE_TOPIC,
draftKey: Composer.DRAFT,
categoryId: currentCategory,
});
return false;
},
});
api.decorateWidget('topic-list:before', (helper) => {
if (api.getCurrentUser()) {
helper.appendChild(helper.createWidget('custom-new-topic-button'));
}
});
</script>
SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 04:52
2
SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 07:58
3
搞定了。@sam 我用完了每日的调用次数……抱歉。然后我跑到我们的 LLAMA 405 B,经过一番来回折腾,我得到了可以工作的代码。我无法想象这会花我多少钱。我可能会在论坛上听到其他人的声音,比如“白痴,有一个设置可以在这个位置完成这件事”。但这对于通过持续的提示修改来获得工作代码来说,是一次有趣的练习。
其中一些关键点是(请注意,其中一些可能不准确,因为我总共只是一名 JavaScript 开发人员和 Discourse 开发人员大约两天):
这是一个由 Discourse 托管的论坛,我没有操作系统访问权限
这是一个插件,所以你不能直接引用 Discourse。
你不能直接引用 Ember
如果你要使用它,请确保将其绑定到 self
然后进入你想要的功能特性。
<script type="text/discourse-plugin" version="1.24.0">
api.modifyClass('component:topic-list', {
pluginId: 'your-plugin-id',
didRender: function() {
const category = this.get('category');
if (!category) {
console.error('未找到类别');
return;
}
const currentUser = this.currentUser;
if (!currentUser) {
console.error('未找到当前用户');
return;
}
const canCreateTopic = currentUser.can_create_topic;
if (canCreateTopic === undefined) {
console.error('未定义 can_create_topic');
return;
}
console.log('category:', category);
console.log('canCreateTopic:', canCreateTopic);
if (category && canCreateTopic) {
const topicListBody = document.querySelector('.topic-list-body');
const listContainer = document.querySelector('.list-container');
const topicList = document.querySelector('.topic-list');
let container = topicListBody || listContainer || topicList;
if (!container) {
container = this.element; // 使用组件的元素作为容器
}
console.log('container:', container);
const existingButton = container.querySelector('.new-topic-button');
if (!existingButton) {
const newTopicButton = document.createElement('a');
newTopicButton.href = '#';
newTopicButton.className = 'new-topic-button';
newTopicButton.setAttribute('data-category-id', category.id);
newTopicButton.textContent = 'New Topic';
const self = this; // 存储组件的上下文
newTopicButton.onclick = (e) => {
e.preventDefault();
const router = api.container.lookup('router:main');
const url = router.generate('new-topic', { queryParams: { category: category.slug } });
router.transitionTo(url);
};
container.prepend(newTopicButton);
console.log('button added');
}
}
}
});
</script>
SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 08:10
4
我说得太早了,那个版本有一个棘手的 didRender 问题,它不想发布到第一个类别以外的任何类别。我让 llama 修复了这个问题。
<script type="text/discourse-plugin" version="1.24.0">
api.modifyClass('component:topic-list', {
pluginId: 'your-plugin-id',
didRender: function() {
const category = this.get('category');
if (!category) {
console.error('找不到类别');
return;
}
const currentUser = this.currentUser;
if (!currentUser) {
console.error('找不到当前用户');
return;
}
const canCreateTopic = currentUser.can_create_topic;
if (canCreateTopic === undefined) {
console.error('未定义 can create topic');
return;
}
console.log('类别:', category);
console.log('canCreateTopic:', canCreateTopic);
if (category && canCreateTopic) {
const topicListBody = document.querySelector('.topic-list-body');
const listContainer = document.querySelector('.list-container');
const topicList = document.querySelector('.topic-list');
let container = topicListBody || listContainer || topicList;
if (!container) {
container = this.element; // 使用组件的元素作为容器
}
console.log('容器:', container);
let newTopicButton = container.querySelector('.new-topic-button');
if (!newTopicButton) {
newTopicButton = document.createElement('a');
newTopicButton.href = '#';
newTopicButton.className = 'new-topic-button';
container.prepend(newTopicButton);
console.log('已添加按钮');
}
newTopicButton.setAttribute('data-category-id', category.id);
newTopicButton.textContent = '新主题';
const self = this; // 存储组件的上下文
newTopicButton.onclick = (e) => {
e.preventDefault();
const router = api.container.lookup('router:main');
const url = router.generate('new-topic', { queryParams: { category: category.slug } });
router.transitionTo(url);
};
}
}
});
</script>
pfaffman
(Jay Pfaffman)
2024 年9 月 21 日 12:07
5
您似乎已经解决了您的问题,就像我写求助帖时经常做的那样。
New Topic Header Button - #67 by patrickemin 提供了一个示例,并且可能正是您想要的。
另外,告诉您的工程师他们可以按“c”键来撰写消息。
3 个赞
SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 14:30
6
在 Central 中,开始新对话按钮位于主题列表的底部。大家都希望将按钮放在顶部。我可能会将其更改为一个小的加号,但这两张截图显示了它。
1 个赞
SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 15:22
7
@pfaffman 我尝试了新的主题标题按钮作为第一次尝试。但是,这与新的 Discourse Central 主题不兼容。
小组件即将消失。使用小组件 API 不是一个好主意。
请使用 Glimmer 组件。
2 个赞
SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 15:36
9
我们还需要从AI rags中移除大量旧内容,并等待小部件模型进行微调。甚至ask.discourse.com也倾向于小部件路线。什么将取代小部件?我将看看是否能让模型吐出考虑到这一点的代码。顺便说一句,我大部分的练习是为了看看我是否能让模型完成这项工作,因为我对js几乎一无所知:)
pfaffman
(Jay Pfaffman)
2024 年9 月 21 日 15:45
10
我懂这种感觉。
Coby David Adams Jr.:
什么将取代小部件?
Glimmer 组件。Somewhere there is a decent topic describing them.
但这里有一个创建组件的示例:
下面是一个插入它的 JavaScript 方法:
插入它的另一种方法是创建连接器,然后插入组件,但初始化器方法的优点是您可以将所需的插件出口传递给初始化器,这样您就可以有一个设置来更改显示位置。
我认为您想找一个调用 shouldDisplay(或类似名称)的示例,如果您希望它仅在某些情况下显示(例如,如果他们已登录)。
4 个赞
SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 15:47
11
我昨晚让 Llama 生成的最终代码没有使用小部件,但也没有使用 Glimmer。我今天晚些时候会再研究一下 Glimmer。
<script type="text/discourse-plugin" version="1.24.0">
api.modifyClass('component:topic-list', {
pluginId: 'your-plugin-id',
didRender: function() {
const category = this.get('category');
if (!category) {
console.error('找不到分类');
return;
}
const currentUser = this.currentUser;
if (!currentUser) {
console.error('找不到当前用户');
return;
}
const canCreateTopic = currentUser.can_create_topic;
if (canCreateTopic === undefined) {
console.error('未定义创建主题的权限');
return;
}
console.log('category:', category);
console.log('canCreateTopic:', canCreateTopic);
if (category && canCreateTopic) {
const topicListBody = document.querySelector('.topic-list-body');
const listContainer = document.querySelector('.list-container');
const topicList = document.querySelector('.topic-list');
let container = topicListBody || listContainer || topicList;
if (!container) {
container = this.element; // 使用组件的元素作为容器
}
console.log('container:', container);
let newTopicButton = container.querySelector('.new-topic-button');
if (!newTopicButton) {
newTopicButton = document.createElement('a');
newTopicButton.href = '#';
newTopicButton.className = 'new-topic-button';
container.prepend(newTopicButton);
console.log('已添加按钮');
}
newTopicButton.setAttribute('data-category-id', category.id);
newTopicButton.textContent = '新主题';
const self = this; // 存储组件的上下文
newTopicButton.onclick = (e) => {
e.preventDefault();
const router = api.container.lookup('router:main');
const url = router.generate('new-topic', { queryParams: { category: category.slug } });
router.transitionTo(url);
};
}
}
});
</script>
注意:主题列表目前未转换为 Glimmer。
但是,如果您将组件附加到插件插座,则应使用 Glimmer。
如果必须附加到小部件,可以使用 RenderGlimmer 来实现。
示例如下:
return {
chosen: [],
button_disabled: true,
};
},
html(attrs, state) {
const contents = [];
contents.push(
new RenderGlimmer(
this,
"div.tag-chooser-component",
hbs`<h3>{{@data.componentHeading}}</h3><TagChooser @id="list-with-tags" @tags={{@data.chosen}} @onChange={{action @data.onChangeUpdateTagSet}}/>
<DButton @disabled={{@data.buttonDisabled}} @action={{@data.actionForClick}} @translatedLabel={{@data.buttonLabel}}/><sub>{{@data.componentInstructions}}</sub>`,
{
...attrs,
chosen: state.chosen,
onChangeUpdateTagSet: this.onChangeUpdateTagSet.bind(this),
actionForClick: this.actionForClick.bind(this),
buttonLabel: I18n.t(themePrefix("tag_intersect_button_label")),
我恳请您在没有先自行学习基础知识的情况下,不要过度依赖 LLM,因为您需要对 LLM 的输出进行最终的质量保证。
您还需要正确地构建解决方案。
在此处阅读有关 EmberJS 的更多信息:
At its core, Ember's UIs are HTML driven - every part of the UI that is shown to the user is defined in a component template somewhere in your application. Because of this, templates are central to Ember, and one of the most important parts of the...
3 个赞
SupportGeek
(Coby David Adams Jr.)
2024 年9 月 21 日 16:55
13
谢谢。我一定会更加努力地学习,因为我对 discourse 和 js 都很陌生。
我在一家人工智能公司工作,所以这也是一次提示工程的练习。
3 个赞
这样你就能很好地了解他们的优缺点了。
我写了第一个 Discourse AI 机器人,名为 Chatbot ,所以我也有一些见解。
2 个赞
sam
(Sam Saffron)
2024 年9 月 21 日 22:40
15
将在系统提示中添加一些特殊指导,以确保“ask”从不推荐使用小部件
5 个赞