위젯

프론트엔드 위젯은 페이지에 추가하여 기능의 일부를 처리할 수 있는 독립적인 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 매핑 및 미디에이터 스토어를 포함합니다.

위젯 책임

위젯은 해당되는 엔터티(담당자, 이터레이션 등)의 가져오기와 업데이트를 담당합니다. 이는 위젯이 항상 데이터를 가져와야 한다는 것을 의미합니다(이미 Apollo 캐시에 없는 경우). 초기 값이 위젯에 제공되더라도 백그라운드에서 GraphQL 쿼리를 수행하여 Apollo 캐시에 저장되어야 합니다.

최종적으로, 전역 응용 프로그램 상태로 Apollo Client 캐시가 있는 경우 사이드바 위젯에 초기 데이터를 전달할 필요가 없어질 것입니다. 그때는 캐시에서 데이터를 검색할 수 있을 것입니다.

GraphQL 쿼리 및 뮤테이션 사용

다양한 엔터티(에픽, 이슈, 병합 요청 등)와 작업하도록 위젯이 유연해야 합니다. 서로 다른 사이드바에 대해 서로 다른 GraphQL 쿼리와 뮤테이션이 필요하기 때문에, 우리는 매핑을 만듭니다:

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

동일한 논리를 쿼리 업데이트에 처리하기 위해 우리는 쿼리 필드에 별칭을 붙입니다. 예를 들어:

  • group 또는 projectworkspace가 됩니다.
  • issue, epic, 또는 mergeRequestissuable이 됩니다.

불행하게도, Apollo는 별칭이 붙은 필드에 typenameundefined로 지정하므로, 우리는 __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']),
},

이러한 구성 요소의 예시를 확인하세요.

병합 요청 위젯

병합 요청 위젯 프레임워크에 특화된 문서를 참조하세요.