const rect = target.getBoundingClientRect();

      const clickEventY = this.groupMenuEvent.clientY;
      const tartgetY = Math.floor((clickEventY - 150) * 0.1) * 10;

      const dialogRef = this.dialog.open(EditInlineInputDialogComponent, {
        width: rect.width,
        height: rect.height,
        panelClass: 'ucap-edit-group-name-dialog',
        data: {
          curValue: group.name,
          placeholder: '그룹명을 입력하세요.',
          left: rect.left,
          top: clickEventY - 100 + rect.height
        }
      });

"TypeError: Cannot read property 'height' of undefined
at ExpansionComponent.onSelectGroupMenu (http://localhost:4200/pages-group-group-page-module.980e746b5ae98aad2c91.hot-update.js:985:47)
at ExpansionComponent_ng_template_11_button_6_Template_button_click_0_listener (http://localhost:4200/pages-group-group-page-module.980e746b5ae98aad2c91.hot-update.js:581:416)
at executeListenerWithErrorHandling (http://localhost:4200/vendor.js:53654:16)
at wrapListenerIn_markDirtyAndPreventDefault (http://localhost:4200/vendor.js:53703:22)
at HTMLButtonElement.<anonymous> (http://localhost:4200/vendor.js:123295:38)
at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:443:35)
at Object.onInvokeTask (http://localhost:4200/vendor.js:70743:33)
at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:442:40)
at Zone.runTask (http://localhost:4200/polyfills.js:211:51)
at ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:524:38)"


switch (menuType) {
  case 'VIEW_PROFILE':
    this.onClickUser(event, userInfo as UserInfo);
    break;
  case 'REGISTER_FAVORITE':
    this.store.dispatch(
      BuddyActions.update({
        req: {
          seq: Number(userInfo.seq),
          isFavorit: !userInfo.isFavorit
        }
      })
    );
    break;
  case 'NICKNAME':
    {
      this.editNickname(event, userInfo, rect);
    }
    break;
  case 'COPY_BUDDY':
    this.eidtUserDialog('COPY_BUDDY', group, userInfo);
    break;
  case 'MOVE_BUDDY':
    this.eidtUserDialog('MOVE_BUDDY', group, userInfo);
    break;
  case 'REMOVE_BUDDY':
    {
      this.removeBuddy(userInfo, group);
    }
    break;
}



private eidtUserDialog(
    type: string,
    group: GroupDetailData,
    userInfo: UserInfoTypes
  ) {
    let title = '';
    let dialogType: GroupUserDialaogType;
    if (type === 'COPY_BUDDY') {
      title = '멤버 복사';
      dialogType = GroupUserDialaogType.Copy;
    } else {
      title = '멤버 이동';
      dialogType = GroupUserDialaogType.Move;
    }
    const dialogRef = this.dialog.open<
      EditUserDialogComponent,
      EditUserDialogData,
      EditUserDialogResult
    >(EditUserDialogComponent, {
      width: '100%',
      height: '100%',
      data: {
        title,
        type: dialogType,
        group,
        userInfo
      }
    });
    dialogRef
      .afterClosed()
      .pipe(
        take(1),
        map((result: EditUserDialogResult) => {
          let targetGroup: GroupDetailData;
          let targetUserSeqs: string[];
          if (result.type === GroupUserDialaogType.Add) {
            targetGroup = result.group;
            targetUserSeqs = [];
            result.selelctUserList.forEach((u) => {
              targetUserSeqs.push(u.seq + '');
            });
            this.store.dispatch(
              GroupActions.updateMember({ targetGroup, targetUserSeqs })
            );
          } else if (result.type === GroupUserDialaogType.Copy) {
            if (!!result.selectGroupList && result.selectGroupList.length > 0) {
              result.selectGroupList.forEach((g) => {
                targetGroup = g;
                targetUserSeqs = [];
                g.userSeqs.map((seq) => {
                  targetUserSeqs.push(seq);
                });
                if (targetUserSeqs.length === 0) {
                  result.selelctUserList.forEach((user) => {
                    targetUserSeqs.push(user.seq as any);
                  });
                } else {
                  result.selelctUserList.forEach((user) => {
                    const find = targetUserSeqs.indexOf(user.seq as any);
                    if (find < 0) {
                      targetUserSeqs.push(user.seq as any);
                    }
                  });
                }
                this.store.dispatch(
                  GroupActions.updateMember({ targetGroup, targetUserSeqs })
                );
              });
            }
          } else if (result.type === GroupUserDialaogType.Move) {
            const fromGroup = result.group;
            let toGroup: GroupDetailData;
            targetUserSeqs = [];
            if (!!result.selectGroupList && result.selectGroupList.length > 0) {
              result.selectGroupList.forEach((g) => {
                toGroup = g;
                targetUserSeqs = [];
                result.selelctUserList.forEach((user) => {
                  targetUserSeqs.push(user.seq as any);
                });
                this.store.dispatch(
                  GroupActions.moveMember({
                    fromGroup,
                    toGroup,
                    targetUserSeq: targetUserSeqs
                  })
                );
              });
            }
          } else if (result.type === GroupUserDialaogType.Create) {
            targetUserSeqs = [];
            result.selelctUserList.forEach((u) => {
              targetUserSeqs.push(u.seq + '');
            });
            this.store.dispatch(
              GroupActions.create({
                groupName: result.groupName,
                targetUserSeqs
              })
            );
          }
        }),
        catchError((err) => {
          return of(err);
        })
      )
      .subscribe();
  }

  private removeBuddy(userInfo: UserInfoF, group: GroupDetailData) {
    const dialogRef = this.dialog.open<
      ConfirmDialogComponent,
      ConfirmDialogData,
      ConfirmDialogResult
    >(ConfirmDialogComponent, {
      data: {
        title: '',
        html: this.i18nService.t('label.confirmRemoveBuddy')
      }
    });
    dialogRef
      .afterClosed()
      .pipe(
        take(1),
        map((result) => {
          if (!!result && result.choice) {
            const trgtUserSeq = group.userSeqs.filter(
              (user) => user + '' !== userInfo.seq + ''
            );

            this.store.dispatch(
              GroupActions.updateMember({
                targetGroup: group,
                targetUserSeqs: trgtUserSeq
              })
            );
          }
        }),
        catchError((err) => {
          return of(err);
        })
      )
      .subscribe();
  }
  private editNickname(event: MouseEvent, userInfo: UserInfoF, rect: any) {
    const clickEventY = event.clientY;

    // const dialogRef = this.dialog.open(EditInlineInputDialogComponent, {
    //   width: rect.width - 30 + '',
    //   height: rect.height,
    //   panelClass: 'ucap-edit-group-name-dialog',
    //   data: {
    //     curValue: userInfo.nickName,
    //     placeholder: '닉네임을 설정하세요.',
    //     left: rect.left + 70,
    //     top: rect.top
    //   }
    // });

    // dialogRef
    //   .afterClosed()
    //   .pipe(
    //     take(1),
    //     map((result) => {
    //       if (
    //         !!result &&
    //         result.choice &&
    //         result.curValue.localeCompare(userInfo.nickName) !== 0
    //       ) {
    //         this.store.dispatch(
    //           BuddyActions.nickname({
    //             req: {
    //               userSeq: Number(userInfo.seq),
    //               nickname: result.curValue
    //             }
    //           })
    //         );
    //       }
    //     }),
    //     catchError((err) => {
    //       return of(err);
    //     })
    //   )
    //   .subscribe();
  }

리팩토링
  셀렉트 이용 
  이벤트가 다른 컴포넌트 시리즈 분리

컴포넌트 후보
  사용자 선택 (chips)
  검색 결과 
    프로필 리스트

그룹 다이얼로그
  생성,
    출력
      그룹명, 그룹 유저 리스트, 조직도, 검색, 검색 결과
    기능
      그룹명 유효성 검사
      그룹 유저 리스트 
        사용자 체크에 대한 처리, 그룹 체크에 대한 처리, 체크박스
  한줄 수정, 
    출력 
      한줄 입력창, 적용 버튼, 취소 버튼
    기능
      한줄 입력에 대한 유효성 검사
      절대 위치에 출력할 수 있게 포지션 계산
  유저 변경(이동, 복사, 생성, 삭제), 

  유저 변경(이동, 복사)
그룹 메뉴
  출력
    메뉴 
    이름 바꾸기
    그룹 삭제
  기능  
    그룹 대화, 쪽지 => 이벤트 호출
    그룹 이름 => position 계산, 적용, 취소에 대한 처리, 액션 처리
    그룹 삭제 => 사용자 확인 다이얼로그 출력 및 액션에 대한 처리

익스팬션 
  프로필 리스트 아이템
    출력
      프로필 메뉴, 프레젠스, 프로핊 이미지, 이름, 직함, 부서, 인트로, 닉네임
    기능
      프로필 보기
      즐겨 찾기 설정
      닉네임 설정
      대화 상대 복사, 이동
      삭제
      마우스오버&리브 이벤트에 대한 버튼 출력
      모어 메뉴 출력 포지션 계산

검색 
  출력
    입력창, 검색 버튼, 입력 삭제 버튼, 회사 리스트
  기능
    입력 이벤트
    검색 액션 처리
    삭제 버튼 액션 처리
    회사 리스트 조회
셀렉트 그룹
  검색
  그룹명 입력
  기존 그룹 리스트
  체크박스
셀렉트 유저
  익스팬션
    프로필 리스트 아이템 
      프레젠스, 프로필 이미지, 이름, 부서, 직함, 체크박스


그룹용 프로필 리스트 아이템  
  마우스오버 -> 버튼 컴포넌트
  
다이얼로그 프로필 리스트 아이템
  체크박스