无法让我的组件中的JS代码编译,错误:SyntaxError: 私有字段必须在封闭的类中使用

在一天结束时,我需要在 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>

@steven.webster @vasanth.mohan

搞定了。@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>

我说得太早了,那个版本有一个棘手的 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>

您似乎已经解决了您的问题,就像我写求助帖时经常做的那样。

New Topic Header Button - #67 by patrickemin 提供了一个示例,并且可能正是您想要的。

另外,告诉您的工程师他们可以按“c”键来撰写消息。

3 个赞

在 Central 中,开始新对话按钮位于主题列表的底部。大家都希望将按钮放在顶部。我可能会将其更改为一个小的加号,但这两张截图显示了它。


1 个赞

@pfaffman 我尝试了新的主题标题按钮作为第一次尝试。但是,这与新的 Discourse Central 主题不兼容。

小组件即将消失。使用小组件 API 不是一个好主意。

请使用 Glimmer 组件。

2 个赞

我们还需要从AI rags中移除大量旧内容,并等待小部件模型进行微调。甚至ask.discourse.com也倾向于小部件路线。什么将取代小部件?我将看看是否能让模型吐出考虑到这一点的代码。顺便说一句,我大部分的练习是为了看看我是否能让模型完成这项工作,因为我对js几乎一无所知:)

我懂这种感觉。

Glimmer 组件。Somewhere there is a decent topic describing them.

但这里有一个创建组件的示例:

下面是一个插入它的 JavaScript 方法:

插入它的另一种方法是创建连接器,然后插入组件,但初始化器方法的优点是您可以将所需的插件出口传递给初始化器,这样您就可以有一个设置来更改显示位置。

我认为您想找一个调用 shouldDisplay(或类似名称)的示例,如果您希望它仅在某些情况下显示(例如,如果他们已登录)。

4 个赞

我昨晚让 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 来实现。

示例如下:

我恳请您在没有先自行学习基础知识的情况下,不要过度依赖 LLM,因为您需要对 LLM 的输出进行最终的质量保证。

您还需要正确地构建解决方案。

在此处阅读有关 EmberJS 的更多信息:

3 个赞

谢谢。我一定会更加努力地学习,因为我对 discourse 和 js 都很陌生。

我在一家人工智能公司工作,所以这也是一次提示工程的练习。

3 个赞

这样你就能很好地了解他们的优缺点了。

我写了第一个 Discourse AI 机器人,名为 Chatbot,所以我也有一些见解。

2 个赞

将在系统提示中添加一些特殊指导,以确保“ask”从不推荐使用小部件

5 个赞