ウィジェット

フロントエンドウィジェットは、スタンドアロンのVueアプリケーションまたはVueコンポーネントツリーで、ページ上に追加して機能の一部を処理できます。

ウィジェットの良い例は、サイドバーの担当者やサイドバーの機密性です。

ウィジェットを作成するとき、以下に説明するいくつかの原則に従うべきです。

Vue Apolloが必要です。

すべてのウィジェットは、同じスタック(Vue + Apollo Client)を使用する必要があります。これを実現するには、アプリケーションルートにVue Apolloを追加するか(ウィジェットをコンポーネントとして使用する場合)、ウィジェットに直接提供する必要があります。サイドバーウィジェットの場合は、発行可能なApollo ClientとApollo Providerを使用します:

import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
import { apolloProvider } from '~/graphql_shared/issuable_client';

function mountConfidentialComponent() {
  new Vue({
    apolloProvider,
    components: {
      SidebarConfidentialityWidget,
    },
    /* ... */
  });
}

必要な注入

すべての編集可能なサイドバーウィジェットは、SidebarEditableItem を使用して折りたたみ/展開状態を処理する必要があります。このコンポーネントは、アプリケーションルートで提供されるcanUpdate プロパティを必要とします。

グローバルステートマッピングなし

ウィジェットはできるだけ再利用できるようにすることを目指しています。そのため、ウィジェットやその子コンポーネントに、外部のステートバインディングを追加することは避けなければなりません。これには Vuex マッピングや Mediator ストアが含まれます。

ウィジェットの責任

ウィジェットは、それが設計されたエンティティ(担当者、イテレーションなど)のフェッチと更新に責任を持ちます。つまり、ウィジェットは常にデータをフェッチする必要があります(Apolloキャッシュにない場合)。ウィジェットに初期値を提供する場合でも、バックグラウンドでGraphQLクエリを実行し、Apolloキャッシュに格納する必要があります。

最終的に、グローバルなアプリケーション状態としてApolloクライアントキャッシュがあれば、サイドバーウィジェットに初期データを渡す必要はなくなります。そうなれば、キャッシュからデータを取得できるようになります。

GraphQLクエリと変異の使用

さまざまなエンティティ(エピック、イシュー、マージリクエストなど)に柔軟に対応できるウィジェットが必要です。異なるサイドバーに対して異なる GraphQL クエリとミューテーションが必要なので、次のように作成します。 マッピング:

export const assigneesQueries = {
  [TYPE_ISSUE]: {
    query: getIssueParticipants,
    mutation: updateAssigneesMutation,
  },
  [TYPE_MERGE_REQUEST]: {
    query: getMergeRequestParticipants,
    mutation: updateMergeRequestParticipantsMutation,
  },
};

クエリの更新で同じロジックを処理するために、クエリフィールドにエイリアスを付けます。例えば

  • groupprojectworkspace
  • issue epic またはmergeRequest は次のようになります。issuable

残念ながら、Apolloはエイリアスされたフィールドにundefinedtypename を割り当てますので、__typename を明示的にフェッチする必要があります:

query issueConfidential($fullPath: ID!, $iid: String) {
  workspace: project(fullPath: $fullPath) {
    __typename
    issuable: issue(iid: $iid) {
      __typename
      id
      confidential
    }
  }
}

他のVueアプリケーションとの通信

ウィジェットの状態の変化(例えば、変異が成功した後)を親アプリケーションに伝える必要がある場合、イベントを発行する必要があります:

updateAssignees(assigneeUsernames) {
  return this.$apollo
    .mutate({
      mutation: this.$options.assigneesQueries[this.issuableType].mutation,
      variables: {...},
    })
    .then(({ data }) => {
      const assignees = data.issueSetAssignees?.issue?.assignees?.nodes || [];
      this.$emit('assignees-updated', assignees);
    })
}

NotesApp のように、別の Vue アプリケーションの変更をリッスンしたい場合があります。この場合、クライアントをインポートし、特定のクエリをリッスンするレンダーレスコンポーネントを使用できます:

import { fetchPolicies } from '~/lib/graphql';
import { confidentialityQueries } from '~/sidebar/constants';
import { defaultClient as gqlClient } from '~/graphql_shared/issuable_client';

created() {
  if (this.issuableType !== IssuableType.Issue) {
    return;
  }

  gqlClient
    .watchQuery({
      query: confidentialityQueries[this.issuableType].query,
      variables: {...},
      fetchPolicy: fetchPolicies.CACHE_ONLY,
    })
    .subscribe((res) => {
      this.setConfidentiality(issuable.confidential);
    });
},
methods: {
  ...mapActions(['setConfidentiality']),
},

このようなコンポーネントの例をご覧ください。

マージリクエストウィジェット

マージリクエストウィジェット拡張フレームワークに固有のドキュメントを参照してください。