diff --git a/documents/업무/5월/2째주/0514.txt b/documents/업무/5월/2째주/0514.txt new file mode 100644 index 0000000..23516d8 --- /dev/null +++ b/documents/업무/5월/2째주/0514.txt @@ -0,0 +1,187 @@ + + + {{ node.groupDetail.name }} + + {{ node.children?.length }} + + + + + + + + + + + + + + + + +
+ + + {{ input.value?.length || 0 }}/20 + + + + + + + + + + +
+ + +@Component({ + selector: 'app-group-input', + templateUrl: './group-input.component.html', + styleUrls: ['./group-input.component.scss'], + + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class GroupInputComponent implements OnInit, OnDestroy { + private ngOnDestroySubject = new Subject(); + + @Input() + set groupName(g: string) { + this._groupName = g; + } + get groupName(): string { + return this._groupName; + } + _groupName: string; + + @Input() + inputPlacholder: string; + + @Input() + dialogType: SelectUserDialogType; + + @Input() + componentSeq: number; + + @Input() + groupList?: GroupDetailData[]; + + @Output() + cancel = new EventEmitter(); + + @Output() + confirm = new EventEmitter(); + + @Output() + completeConfirm = new EventEmitter(); + + constructor( + private formBuilder: FormBuilder, + private i18nService: I18nService + ) {} + + inputForm: FormGroup; + + ngOnInit(): void { + this.inputForm = this.formBuilder.group({ + groupName: [ + this.groupName, + [ + Validators.required + // StringUtil.includes(, CharactorType.Special), + // this.checkBanWords(), + // this.checkSameName() + ] + ] + }); + } + + ngOnDestroy(): void { + if (!!this.ngOnDestroySubject) { + this.ngOnDestroySubject.complete(); + } + } + + getGroupName(): string { + return this.inputForm.get('groupName').value; + } + + onKeyupGroupName() { + this.inputForm.get('groupName').markAsTouched(); + } + + checkSameName(): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } | null => { + if ( + !control || + !control.value || + !this.groupList || + 0 === this.groupList.length + ) { + return null; + } + const v = (control.value as string).trim(); + const ban = -1 < this.groupList.findIndex((g) => g.name === v); + return ban ? { groupNameSamed: { value: control.value } } : null; + }; + } + + onCancel() { + this.cancel.emit(); + } + + onConfirm() { + this.confirm.emit(); + } + + onCompleteConfirm() { + this.completeConfirm.emit(); + } +} diff --git a/documents/업무/5월/2째주/0515.txt b/documents/업무/5월/2째주/0515.txt new file mode 100644 index 0000000..2dc9422 --- /dev/null +++ b/documents/업무/5월/2째주/0515.txt @@ -0,0 +1 @@ +5, 22, 23, 0, 16 diff --git a/documents/업무/5월/2째주/Untitled-1.html b/documents/업무/5월/2째주/Untitled-1.html new file mode 100644 index 0000000..df54681 --- /dev/null +++ b/documents/업무/5월/2째주/Untitled-1.html @@ -0,0 +1,80 @@ + + + + + + + + + {{ 'category.favorite' | ucapI18n }} + + {{ node.children?.length }} + + + + + {{ node.groupDetail.name }} + + {{ node.children?.length }} + + + + + + + + + + + + + + {{ 'category.default' | ucapI18n }} + + {{ node.children?.length }} + + + \ No newline at end of file diff --git a/documents/업무/5월/2째주/create-chat.dialog.component.html b/documents/업무/5월/2째주/create-chat.dialog.component.html new file mode 100644 index 0000000..826f8bd --- /dev/null +++ b/documents/업무/5월/2째주/create-chat.dialog.component.html @@ -0,0 +1,71 @@ + + + {{ data.title }} + + + +
+ +
+ +
+
+ + +
+ + + + {{ userInfo.name }} + clear + + +
+ + + + {{ selectedUserList.length }} / 300 + + + + + + + + + + {{ selectedUserList.length }} + + + +
diff --git a/documents/업무/5월/2째주/create-chat.dialog.component.ts b/documents/업무/5월/2째주/create-chat.dialog.component.ts new file mode 100644 index 0000000..cb40ee9 --- /dev/null +++ b/documents/업무/5월/2째주/create-chat.dialog.component.ts @@ -0,0 +1,215 @@ +import { + Component, + OnInit, + OnDestroy, + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Inject, + ViewChild, + ComponentFactoryResolver, + ViewContainerRef, + ComponentRef +} from '@angular/core'; +import { UserInfo, GroupDetailData } from '@ucap/protocol-sync'; +import { + UserInfoSS, + UserInfoF, + UserInfoDN, + DeptInfo +} from '@ucap/protocol-query'; + +import { Store, select } from '@ngrx/store'; + +import { Subject, combineLatest } from 'rxjs'; +import { AppAuthenticationService } from '@app/services/app-authentication.service'; +import { SelectUserDialogType } from '@app/types'; +import { RoomInfo, UserInfo as RoomUserInfo } from '@ucap/protocol-room'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { SelectUserSectionComponent } from '../../select-user.section.component'; +import { GroupActions } from '@ucap/ng-store-group'; +import { UserInfoTypes } from '../profile-list-item.component'; + +import { GroupInputComponent } from '../group-input.component'; + +export interface CreateChatDialogData { + type?: SelectUserDialogType; + title: string; + /** CASE :: EditMember */ + group?: GroupDetailData; + /** CASE :: EventForward */ + ignoreRoom?: RoomInfo[]; + /** CASE :: EditChatMember */ + curRoomUser?: ( + | UserInfo + | UserInfoSS + | UserInfoF + | UserInfoDN + | RoomUserInfo + )[]; +} +export interface CreateChatDialogResult { + choice: boolean; + groupName?: string; + oldGroup?: GroupDetailData; + selectedUserList?: ( + | UserInfo + | UserInfoSS + | UserInfoF + | UserInfoDN + | RoomUserInfo + )[]; + selectedRoom: RoomInfo; +} + +@Component({ + selector: 'app-create-chat.dialog', + templateUrl: './create-chat.dialog.component.html', + styleUrls: ['./create-chat.dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateChatDialogComponent implements OnInit, OnDestroy { + @ViewChild('selectBoxUserComponent', { static: false }) + selectBoxUserComponent: SelectUserSectionComponent; + @ViewChild('dialogContainer', { static: true, read: ViewContainerRef }) + dialogContainer: ViewContainerRef; + + componentRef: ComponentRef; + + constructor( + public dialogRef: MatDialogRef< + CreateChatDialogData, + CreateChatDialogResult + >, + @Inject(MAT_DIALOG_DATA) public data: CreateChatDialogData, + private changeDetectorRef: ChangeDetectorRef, + private store: Store, + private appAuthenticationService: AppAuthenticationService, + private cfResolver: ComponentFactoryResolver + ) {} + + private ngOnDestroySubject = new Subject(); + + selectedUserList: UserInfoTypes[] = []; + SelectUserDialogType = SelectUserDialogType; + selectedRoom: RoomInfo; + + groupName: string; + + ngOnInit(): void { + this.loadComponent(); + } + + ngOnDestroy(): void { + if (!!this.ngOnDestroySubject) { + this.ngOnDestroySubject.complete(); + } + this.componentRef.destroy(); + } + + loadComponent() { + switch (this.data.type) { + case SelectUserDialogType.NewGroup: + case SelectUserDialogType.ModifyGroup: + { + this.dialogContainer.clear(); + const factory = this.cfResolver.resolveComponentFactory( + GroupInputComponent + ); + + this.componentRef = this.dialogContainer.createComponent(factory); + const cpInstance = this.componentRef.instance; + cpInstance.dialogType = this.data.type; + + cpInstance.groupName = + !!this.data.group && !!this.data.group.name + ? this.data.group.name + : ''; + cpInstance.inputPlacholder = '그룹'; + cpInstance.cancel.subscribe(() => { + this.dialogRef.close(); + }); + cpInstance.confirm.subscribe(() => { + this.groupName = this.componentRef.instance.getGroupName(); + this.doAction(); + }); + cpInstance.completeConfirm.subscribe(() => { + this.groupName = this.componentRef.instance.getGroupName(); + this.showSelectUserComponent(); + }); + } + break; + case SelectUserDialogType.NewChat: + { + // 새로운 대화 유형 & 대화방 이름 섹션 컴포넌트 + // 유저 선택 컴포넌트 + } + break; + case SelectUserDialogType.EditChatMember: + { + // 유저 선택 컴포넌트 + } + break; + case SelectUserDialogType.EditMember: + { + // 그룹 멤버 관리 컴포넌트 + // 유저 선택 컴포넌트 + } + break; + case SelectUserDialogType.MessageForward: + { + // 유저 선택 컴포넌트 + } + break; + } + } + onClickChoice(choice: boolean) { + if (!choice) { + this.dialogRef.close(); + return; + } + } + getBtnValid() {} + getChipsRemoveYn(userInfo: UserInfo) {} + onClickDeleteUser(userInfo: UserInfo) {} + + onChangeSelectedUserList(userList: UserInfoTypes[]) { + this.selectedUserList = userList; + this.changeDetectorRef.markForCheck(); + } + + doAction() { + this.dialogRef.close({ + choice: true, + selectedUserList: this.selectedUserList, + selectedRoom: this.selectedRoom, + groupName: this.groupName, + oldGroup: undefined + }); + } + + private showSelectUserComponent() { + this.dialogContainer.clear(); + const factory = this.cfResolver.resolveComponentFactory( + SelectUserSectionComponent + ); + + this.componentRef = this.dialogContainer.createComponent(factory); + this.componentRef.instance.cancel.subscribe(() => { + if ( + this.data.type === SelectUserDialogType.NewGroup || + this.data.type === SelectUserDialogType.ModifyGroup + ) { + this.loadComponent(); + } + }); + this.componentRef.instance.confirm.subscribe(() => { + this.doAction(); + }); + + this.componentRef.instance.changeUserList.subscribe((list) => { + this.selectedUserList = list; + }); + } +} diff --git a/documents/업무/5월/2째주/profile.component.html b/documents/업무/5월/2째주/profile.component.html new file mode 100644 index 0000000..1b9f5b7 --- /dev/null +++ b/documents/업무/5월/2째주/profile.component.html @@ -0,0 +1,211 @@ +
+ +
+ + + + +
+ + + + + +
+
+ + + +
+ + + + + +
+
+ +
+ +
diff --git a/documents/업무/5월/2째주/profile.component.scss b/documents/업무/5월/2째주/profile.component.scss new file mode 100644 index 0000000..ba32fa3 --- /dev/null +++ b/documents/업무/5월/2째주/profile.component.scss @@ -0,0 +1,222 @@ +@charset 'UTF-8'; + +@import '../../../../../assets/scss/components.scss'; + +.mainProfile { + height: calc(100% - 30px); + min-width: 450px; + margin: { + left: 30px; + bottom: 30px; + } + @include screen(mid) { + height: auto; + } + //margin: 30px; + background-image: url(/assets/images/bg/bg_profile1.svg), + url(/assets/images/bg/bg_profile2.svg), + url(/assets/images/bg/bg_profile3.svg), + url(/assets/images/bg/bg_profile4.svg), + url(/assets/images/bg/bg_profile5.svg), $bg-linear-gradient; + background-repeat: no-repeat; + background-position: -213px -223px, 433px 95px, 489px 72px, 433px 517px, + 335px 634px, 0 0; + .profile-card-box { + display: flex; + flex-direction: column; + padding: 60px 8.7%; + width: 100%; + position: relative; + .user-profile-info { + display: inline-flex; + flex-direction: row; + align-items: center; + // Profile thumb////////////////// + .user-profile-thumb { + @include profile-avatar-default( + 10px 0 0, + 18.6, + $green, + 30px + ); //오른 아래 공간, 모바일 온라인 아이콘 크기, 모바일 아이콘 색, 모바일 아이콘 bg크기 + padding: 10px 0 0; + margin-left: -14px; + align-self: start; + .presence { + //PC 상태 + @include presence-state(14px); //원크기 + margin-top: -10px; + } + .profileImage { + @include avatar-img(128px, 0); //아바타 크기, 왼쪽공간 + border: 3px solid $white; + } + .btn-profile-ctrl { + position: absolute; + bottom: 0; + right: 0; + } + } + //////////////////Profile thumb // + .userInfo { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + padding-left: 38px; + .user-n-g { + display: flex; + flex-flow: row-reverse nowrap; + align-items: flex-end; + height: 44px; + .name { + font: { + size: 26px; + weight: 600; + } + color: $gray-re20; + order: 1; + -ms-flex-order: 1; + } + .grade { + font: { + size: 18px; + } + color: #f1f1f1; + margin-left: 6px; + order: 0; + -ms-flex-order: 0; + } + & + .deptName { + margin-top: 9px; + } + } + .deptName { + font-size: 22px; + color: $white; + line-height: 25px; + font-weight: 600; + } + .nickName { + display: flex; + flex-direction: row; + margin-top: 18px; + align-items: center; + .nickName-info { + padding: 0 16px; + height: 30px; + line-height: 30px; + border-radius: 15px; + border: solid 1px #fc5182; + background-color: rgba(255, 255, 255, 0.95); + color: $gray-re9; + font-size: 14px; + } + button { + } + } + .address-txt { + font-size: 16px; + line-height: 21px; + color: $gray-re3; + margin-top: 20px; + } + } + .btn-profile-add { + position: absolute; + z-index: 5; + top: 40px; + right: 40px; + button { + margin: 0 2px; + &.btn-star-add { + line-height: 24px !important; + } + } + } + } + .btn-partner-set { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 25px; + border-top: 1px solid rgba(255, 255, 255, 0.8); + border-bottom: 1px solid rgba(255, 255, 255, 0.8); + height: 70px; + margin-top: 30px; + img { + vertical-align: top; + } + } + .my-input { + display: flex; + flex-flow: row nowrap; + justify-content: space-between; + margin: 0; + width: 100%; + border-bottom: 1px solid $white; + margin-top: 78px; + .my-in-input { + font-size: 16px; + color: $gray-re3; + flex-grow: 1; + height: 24px; + line-height: 24px; + margin-top: 8px; + } + button { + margin-bottom: 5px; + } + } + .user-profile-info-list { + margin-top: 60px; + ul { + display: flex; + flex-direction: column; + justify-content: space-between; + height: 250px; + li { + font-size: 16px; + font-weight: 600; + color: $brown; + span { + width: 100px; + height: 34px; + border-radius: 18px; + border: solid 1px #f8f9fd; + background-color: #aaa0a5; + font-size: 14px; + font-weight: 600; + display: inline-flex; + align-items: center; + justify-content: center; + color: $white; + margin-right: 40px; + } + } + } + } + } + + ///////////////////////////////////////////////////////////////////////////////// 제거 + .profile-card { + //mat-card + width: 100%; + background-color: transparent; + box-shadow: none; + .profileImage { + width: 126px; + height: 126px; + border-radius: 50%; + border: 3px solid $white; + box-sizing: border-box; + overflow: hidden; + display: flex; + img { + display: flex; + align-items: center; + } + } + } + ///////////////////////////////////////////////////////////////////////////////////// +} diff --git a/documents/업무/5월/2째주/profile.component.ts b/documents/업무/5월/2째주/profile.component.ts new file mode 100644 index 0000000..1013027 --- /dev/null +++ b/documents/업무/5월/2째주/profile.component.ts @@ -0,0 +1,288 @@ +import { + Component, + OnInit, + OnDestroy, + ChangeDetectionStrategy, + ChangeDetectorRef, + Input, + Output, + EventEmitter, + ViewChild, + ElementRef +} from '@angular/core'; + +import { AppKey } from '@app/types/app-key.type'; +import { LoginSession } from '@app/models/login-session'; +import { Subject } from 'rxjs'; +import { UserInfoSS, AuthResponse } from '@ucap/protocol-query'; +import { OpenProfileOptions } from '@ucap/protocol-buddy'; +import { FileUploadItem } from '@ucap/api'; +import { FormControl } from '@angular/forms'; +import { WorkStatusType } from '@ucap/protocol'; +import { I18nService } from '@ucap/ng-i18n'; + +@Component({ + selector: 'app-group-profile', + templateUrl: './profile.component.html', + styleUrls: ['./profile.component.scss'], + + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ProfileComponent implements OnInit, OnDestroy { + @Input() + set userInfo(u: UserInfoSS) { + this._userInfo = u; + } + get userInfo(): UserInfoSS { + return this._userInfo; + } + _userInfo: UserInfoSS; + @Input() + isMe: boolean; + @Input() + isBuddy: boolean; + @Input() + isFavorite: boolean; + @Input() + myMadn?: string; + @Input() + canVideoConfernece: boolean; + + @Output() + toggleFavorite = new EventEmitter<{ + userInfo: UserInfoSS; + isFavorite: boolean; + }>(); + @Output() + toggleBuddy = new EventEmitter<{ + userInfo: UserInfoSS; + isBuddy: boolean; + }>(); + @Output() + openChat = new EventEmitter(); + @Output() + sendCall = new EventEmitter(); + @Output() + sendSms = new EventEmitter(); + @Output() + createConference = new EventEmitter(); + @Output() + sendMessage = new EventEmitter(); + + /////////////////////////////////////////////// + + @Input() + profileImageRoot: string; + + @Input() + openProfileOptions?: OpenProfileOptions; + @Input() + useBuddyToggleButton: boolean; + @Input() + authInfo: AuthResponse; + @Output() + profileImageView = new EventEmitter(); + @Output() + uploadProfileImage = new EventEmitter(); + @Output() + updateIntro = new EventEmitter(); + + @ViewChild('profileImageFileInput', { static: false }) + profileImageFileInput: ElementRef; + + userIntroFormControl = new FormControl(''); + profileImageFileUploadItem: FileUploadItem; + + private ngOnDestroySubject = new Subject(); + + constructor(private i18nService: I18nService) {} + + ngOnInit(): void { + console.log(this.isMe); + } + + ngOnDestroy(): void { + if (!!this.ngOnDestroySubject) { + this.ngOnDestroySubject.complete(); + } + } + + onToggleFavorit() { + this.toggleFavorite.emit({ + userInfo: this.userInfo, + isFavorite: !this.isFavorite + }); + } + + onClickToggleBuddy() { + this.toggleBuddy.emit({ + userInfo: this.userInfo, + isBuddy: !this.isBuddy + }); + } + + onClickActionButton(event: MouseEvent, type: string): void { + event.preventDefault(); + event.stopPropagation(); + + switch (type) { + case 'CHAT': + this.onClickOpenChat(); + break; + case 'MESSAGE': + this.onClickMessage(); + break; + case 'SMS': + this.onClickSMS(); + break; + case 'CALL_MOBILE': + this.onClickCall('MOBILE'); + break; + case 'CALL_LINE': + this.onClickCall('LINE'); + break; + case 'CONFERENCE': + this.onClickVideoConference(); + break; + } + } + + onClickOpenChat() { + this.openChat.emit(this.userInfo); + } + + onClickCall(type: string) { + let calleeNumber = ''; + + if (type === 'LINE') { + calleeNumber = this.userInfo.lineNumber; + } else { + calleeNumber = this.userInfo.hpNumber; + } + this.sendCall.emit(calleeNumber); + } + + onClickSMS() { + this.sendSms.emit(this.userInfo.hpNumber); + } + + onClickVideoConference() { + this.createConference.emit(Number(this.userInfo.seq)); + } + + onClickMessage() { + this.sendMessage.emit(this.userInfo); + } + + isDisabledCallButton(type: string): boolean { + if (!this.myMadn || this.myMadn.trim().length === 0) { + if (type === 'LINE' || type === 'MOBILE') { + return true; + } + } + + if (type === 'LINE') { + if ( + !!this.userInfo && + !!this.userInfo.lineNumber && + this.userInfo.lineNumber.trim().length > 0 + ) { + return false; + } else { + return true; + } + } else if (type === 'MOBILE') { + if ( + !!this.userInfo && + !!this.userInfo.hpNumber && + this.userInfo.hpNumber.trim().length > 0 + ) { + return false; + } else { + return true; + } + } else if (type === 'SMS') { + // const smsUtils = new SmsUtils( + // this.sessionStorageService, + // this.nativeService + // ); + // return !smsUtils.getAuthSms(); + } + + return true; + } + + /////////////////////////////////////////////// + + onClickProfileImageView() { + this.profileImageView.emit(); + } + + onApplyIntroMessage(intro: string) { + if (intro.trim().length < 1) { + this.updateIntro.emit(' '); + } else { + this.updateIntro.emit(intro); + } + } + + onChangeFileInput() { + this.profileImageFileUploadItem = FileUploadItem.fromFiles( + this.profileImageFileInput.nativeElement.files + )[0]; + + this.uploadProfileImage.emit(this.profileImageFileUploadItem); + + this.profileImageFileInput.nativeElement.value = ''; + } + + getWorkstatus(userInfo: UserInfoSS): string { + let workstatus = ''; + if (!!userInfo && !!userInfo.workstatus) { + switch (userInfo.workstatus) { + case WorkStatusType.VacationAM: + workstatus = '오전'; + break; + case WorkStatusType.VacationPM: + workstatus = '오후'; + break; + case WorkStatusType.VacationAll: + workstatus = '휴가'; + break; + case WorkStatusType.LeaveOfAbsence: + workstatus = '휴직'; + break; + case WorkStatusType.LongtermRefresh: + workstatus = '장기'; + break; + } + } + + return workstatus; + } + getWorkstatusStyle(userInfo: UserInfoSS): string { + // morning-off: 오전 afternoon-off: 오후 day-off: 휴가 long-time: 장기 leave-of-absence: 휴직 + let style = ''; + if (!!userInfo && !!userInfo.workstatus) { + switch (userInfo.workstatus) { + case WorkStatusType.VacationAM: + style = 'morning-off'; + break; + case WorkStatusType.VacationPM: + style = 'afternoon-off'; + break; + case WorkStatusType.VacationAll: + style = 'day-off'; + break; + case WorkStatusType.LeaveOfAbsence: + style = 'leave-of-absence'; + break; + case WorkStatusType.LongtermRefresh: + style = 'long-time'; + break; + } + } + + return style; + } +} diff --git a/documents/업무/5월/2째주/ucap-angular.zip b/documents/업무/5월/2째주/ucap-angular.zip new file mode 100644 index 0000000..6ff272b Binary files /dev/null and b/documents/업무/5월/2째주/ucap-angular.zip differ diff --git a/documents/업무/5월/2째주/ucap-lg-mockup.zip b/documents/업무/5월/2째주/ucap-lg-mockup.zip new file mode 100644 index 0000000..12693f3 Binary files /dev/null and b/documents/업무/5월/2째주/ucap-lg-mockup.zip differ diff --git a/documents/업무/5월/2째주/ucap-lg-web.zip b/documents/업무/5월/2째주/ucap-lg-web.zip new file mode 100644 index 0000000..130aac6 Binary files /dev/null and b/documents/업무/5월/2째주/ucap-lg-web.zip differ diff --git a/documents/업무/5월/2째주/ucap.zip b/documents/업무/5월/2째주/ucap.zip new file mode 100644 index 0000000..cdec216 Binary files /dev/null and b/documents/업무/5월/2째주/ucap.zip differ diff --git a/weekly-report/5월/주간보고_박병은_2020.0515.pptx b/weekly-report/5월/주간보고_박병은_2020.0515.pptx new file mode 100644 index 0000000..885b260 Binary files /dev/null and b/weekly-report/5월/주간보고_박병은_2020.0515.pptx differ