デフォルトのグループページを/messagesに変更

こんにちは。

/g ページからグループにアクセスする際、グループの URL が /g/group-slug/members ではなく /g/group-slug/messages を指すようにする方法はありますか?

グループメッセージに使用するグループがいくつかあります。ユーザーがグループのメッセージに到達するまでのクリック数を減らすことができれば、非常に役立ちます。これは、グループメンバーの表示よりも私たちにとって重要です。

直接リンクでこれを行うことは知っていますが、動的でユーザー中心の /g?type=my ページから行いたいのです。

「いいね!」 4

これらは通常のリンクではありません。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 ページにフォールバックします。

「いいね!」 7

素晴らしい!見事に機能しました。ありがとうございます。


後で…

すみません、フォローアップの問題が発生したので、少し助けが必要です!

いくつかのグループには、メッセージがないにもかかわらず、/g/group-slug/messages が表示されたままです。

詳しく調べると、過去にメッセージがあり、それがトピックに変換されたり削除されたりしていました。Data Explorer によると、これらのグループは Groups テーブルで has_messagesTrue になっています。

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

グループを削除して再作成する以外に、何か提案はありますか(それはあまりやりたくありません)。

「いいね!」 3

レールコンソールでこの行を実行するだけで、すべてのグループが更新されるはずです。

Group.refresh_has_messages!
「いいね!」 1

これで2つを除くすべてが機能しました。ありがとうございます。残りのしつこい2つは削除して再作成する必要があると思います!

これを実行したところ、その理由を発見しました。これは軽微な#バグです。

グループプライベートメッセージをトピックに変換する際に、招待者の情報が保持されます。トピックが元に戻された場合は便利ですが、Group.refresh_has_messages! が実行されたときに誤ってカウントされることを意味します。

「いいね!」 2

@メンションされたグループをクリックしてグループに移動する際に表示されるリンクもハイジャックすることは可能でしょうか?URLに頼らずにグループにアクセスできるのは、これら2つの方法だけだと思います。

私が今求めているのは(欲張りですよね?)、「/g」ページのリンクと同じように、すべてのグループへのリンクが機能するようにすることです。

「いいね!」 1

@Johani、これは可能ですか?調べてみましたが、明らかに私の能力を超えています。

はい、テーマ/コンポーネントのヘッダータブで次のようなものを試すことができます。わかりやすいようにスニペットにコメントを残しておきました。準備ができたら削除できます。

同じルールが適用されます。ユーザーがグループのメンバーであり、グループにメッセージがある場合、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>
「いいね!」 2

素晴らしい!カードを使用するあらゆるケースでうまく機能します。

現在、方向性が定められていないリンクが1つあります。それは、グループプライベートメッセージ内のグループへのリンクです。これは、グループメッセージからグループ(したがって受信トレイ)に移動するのに非常に便利です。

これもキャッチできると思いますか?

(ちなみに、これで完了したらTCにパッケージ化し、トピックを作成して、他の人がアクセスしやすいようにします)

「いいね!」 2

それらのリンクは、グループデータがすべて必要ではないため、わずかに異なるシリアライザーを使用しています。

それでも、初期ページビューで現在のユーザーのグループのフィルタリングされたリストを保存し、それらをメンバーシップを確認するための参照として使用できます。この情報はすでに初期ペイロードで利用可能なので、追加のリクエストなどのオーバーヘッドはありません。以下のようなものです。

<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>

このスニペットを独自のスクリプトタグ内に保持し、他のスニペットと一緒にヘッダーに追加してください。ユーザーがログインしていない場合にすぐに終了するため、別にしておきます。

「いいね!」 1

:partying_face: 到着しました!モバイルでも見事に動作します。

ジョー、驚くべき粘り強さに感謝します。私も約束を果たして、その Theme component に取り掛からなければなりませんね?

後ほど…
できました:

「いいね!」 1

これを完全に完了するために、もう一つ手伝ってほしいことがあります。図々しいお願いだとわかっています。

現在、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/`;
      }
「いいね!」 1

もう大丈夫です!!! @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_groupstopic_allowed_groupsテーブルもクリーンアップする必要があるかもしれません。

 TopicGroup.where(group_id: XXX).destroy_all
 TopicAllowedGroup.where(group_id: XXX).destroy_all

このトピックは30日後に自動的に閉じられました。返信はもうできません。