upload of profile image is implemented
This commit is contained in:
parent
4da93a5351
commit
eb542bd923
|
@ -2,35 +2,67 @@ import { DeviceType } from '@ucap-webmessenger/core';
|
||||||
import {
|
import {
|
||||||
APIRequest,
|
APIRequest,
|
||||||
APIResponse,
|
APIResponse,
|
||||||
APIEncoder,
|
|
||||||
APIDecoder,
|
APIDecoder,
|
||||||
ParameterUtil
|
ParameterUtil,
|
||||||
|
APIFormDataEncoder,
|
||||||
|
JsonAnalization,
|
||||||
|
StatusCode
|
||||||
} from '@ucap-webmessenger/api';
|
} from '@ucap-webmessenger/api';
|
||||||
|
import { FileUploadItem } from '../models/file-upload-item';
|
||||||
|
|
||||||
export interface FileProfileSaveRequest extends APIRequest {
|
export interface FileProfileSaveRequest extends APIRequest {
|
||||||
userSeq: number;
|
userSeq: number;
|
||||||
deviceType: DeviceType;
|
deviceType: DeviceType;
|
||||||
token: string;
|
token: string;
|
||||||
file?: File;
|
file?: File;
|
||||||
|
fileUploadItem: FileUploadItem;
|
||||||
intro?: string;
|
intro?: string;
|
||||||
initProfileImage?: boolean;
|
initProfileImage?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileProfileSaveResponse extends APIResponse {
|
export interface FileProfileSaveResponse extends APIResponse {
|
||||||
ProfileURL?: string;
|
profileURL?: string;
|
||||||
ProfileSubDir?: string;
|
profileSubDir?: string;
|
||||||
|
returnJson?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileProfileEncodeMap = {};
|
const fileProfileEncodeMap = {
|
||||||
|
userSeq: 'p_user_seq',
|
||||||
|
deviceType: 'p_device_type',
|
||||||
|
token: 'p_token',
|
||||||
|
file: 'file',
|
||||||
|
intro: 'p_intro',
|
||||||
|
initProfileImage: 'p_init_profile_img_yn'
|
||||||
|
};
|
||||||
|
|
||||||
export const encodeFileProfileSave: APIEncoder<FileProfileSaveRequest> = (
|
export const encodeFileProfileSave: APIFormDataEncoder<FileProfileSaveRequest> = (
|
||||||
req: FileProfileSaveRequest
|
req: FileProfileSaveRequest
|
||||||
) => {
|
) => {
|
||||||
return ParameterUtil.encode(fileProfileEncodeMap, req);
|
const extraParams: any = {};
|
||||||
|
|
||||||
|
extraParams.userSeq = String(req.userSeq);
|
||||||
|
if (!!req.initProfileImage) {
|
||||||
|
extraParams.initProfileImage = req.initProfileImage ? 'Y' : 'N';
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParameterUtil.encodeFormData(fileProfileEncodeMap, req, extraParams);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decodeFileProfileSave: APIDecoder<FileProfileSaveResponse> = (
|
export const decodeFileProfileSave: APIDecoder<FileProfileSaveResponse> = (
|
||||||
res: any
|
res: any
|
||||||
) => {
|
) => {
|
||||||
return {} as FileProfileSaveResponse;
|
try {
|
||||||
|
const json = JsonAnalization.receiveAnalization(res);
|
||||||
|
return {
|
||||||
|
statusCode: json.StatusCode,
|
||||||
|
profileURL: json.ProfileURL,
|
||||||
|
profileSubDir: json.ProfileSubDir,
|
||||||
|
returnJson: res
|
||||||
|
} as FileProfileSaveResponse;
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
statusCode: StatusCode.Fail,
|
||||||
|
errorMessage: e
|
||||||
|
} as FileProfileSaveResponse;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -94,15 +94,29 @@ export class CommonApiService {
|
||||||
req: FileProfileSaveRequest,
|
req: FileProfileSaveRequest,
|
||||||
fileProfileSaveUrl?: string
|
fileProfileSaveUrl?: string
|
||||||
): Observable<FileProfileSaveResponse> {
|
): Observable<FileProfileSaveResponse> {
|
||||||
return this.httpClient
|
const httpReq = new HttpRequest(
|
||||||
.post<any>(
|
'POST',
|
||||||
!!fileProfileSaveUrl ? fileProfileSaveUrl : this.urls.fileProfileSave,
|
!!fileProfileSaveUrl ? fileProfileSaveUrl : this.urls.fileProfileSave,
|
||||||
{},
|
encodeFileProfileSave(req),
|
||||||
{
|
{ reportProgress: true, responseType: 'text' as 'json' }
|
||||||
params: encodeFileProfileSave(req)
|
);
|
||||||
|
|
||||||
|
const progress = req.fileUploadItem.uploadStart();
|
||||||
|
|
||||||
|
return this.httpClient.request(httpReq).pipe(
|
||||||
|
filter(event => {
|
||||||
|
if (event instanceof HttpResponse) {
|
||||||
|
return true;
|
||||||
|
} else if (HttpEventType.UploadProgress === event.type) {
|
||||||
|
progress.next(Math.round((100 * event.loaded) / event.total));
|
||||||
}
|
}
|
||||||
)
|
return false;
|
||||||
.pipe(map(res => decodeFileProfileSave(res)));
|
}),
|
||||||
|
map((event: HttpResponse<any>) => {
|
||||||
|
req.fileUploadItem.uploadComplete();
|
||||||
|
return decodeFileProfileSave(event.body);
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public urlForFileTalkDownload(
|
public urlForFileTalkDownload(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<ucap-profile-profile
|
<ucap-profile-profile
|
||||||
[userInfo]="data.userInfo"
|
[userInfo]="userInfo"
|
||||||
[profileImageRoot]="sessionVerinfo.profileRoot"
|
[profileImageRoot]="sessionVerinfo.profileRoot"
|
||||||
[isMe]="isMe"
|
[isMe]="isMe"
|
||||||
[isBuddy]="isBuddy"
|
[isBuddy]="isBuddy"
|
||||||
|
@ -7,5 +7,6 @@
|
||||||
(openChat)="onClickChat($event)"
|
(openChat)="onClickChat($event)"
|
||||||
(toggleFavorit)="onClickToggleFavorit($event)"
|
(toggleFavorit)="onClickToggleFavorit($event)"
|
||||||
(toggleBuddy)="onClickToggleBuddy($event)"
|
(toggleBuddy)="onClickToggleBuddy($event)"
|
||||||
|
(uploadProfileImage)="onUploadProfileImage($event)"
|
||||||
>
|
>
|
||||||
</ucap-profile-profile>
|
</ucap-profile-profile>
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { Store, select } from '@ngrx/store';
|
||||||
import * as AppStore from '@app/store';
|
import * as AppStore from '@app/store';
|
||||||
import * as ChatStore from '@app/store/messenger/chat';
|
import * as ChatStore from '@app/store/messenger/chat';
|
||||||
import * as SyncStore from '@app/store/messenger/sync';
|
import * as SyncStore from '@app/store/messenger/sync';
|
||||||
|
import * as AuthenticationStore from '@app/store/account/authentication';
|
||||||
|
|
||||||
import { UserInfo, GroupDetailData } from '@ucap-webmessenger/protocol-sync';
|
import { UserInfo, GroupDetailData } from '@ucap-webmessenger/protocol-sync';
|
||||||
import {
|
import {
|
||||||
|
@ -15,12 +16,28 @@ import {
|
||||||
UserInfoF,
|
UserInfoF,
|
||||||
UserInfoDN
|
UserInfoDN
|
||||||
} from '@ucap-webmessenger/protocol-query';
|
} from '@ucap-webmessenger/protocol-query';
|
||||||
import { DialogService, ConfirmDialogComponent, ConfirmDialogData, ConfirmDialogResult } from '@ucap-webmessenger/ui';
|
import {
|
||||||
|
DialogService,
|
||||||
|
ConfirmDialogComponent,
|
||||||
|
ConfirmDialogData,
|
||||||
|
ConfirmDialogResult,
|
||||||
|
SnackBarService
|
||||||
|
} from '@ucap-webmessenger/ui';
|
||||||
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
|
||||||
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||||
import { map } from 'rxjs/operators';
|
import { map, take, finalize } from 'rxjs/operators';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { SelectGroupDialogComponent, SelectGroupDialogData, SelectGroupDialogResult } from '../group/select-group.dialog.component';
|
import {
|
||||||
|
SelectGroupDialogComponent,
|
||||||
|
SelectGroupDialogData,
|
||||||
|
SelectGroupDialogResult
|
||||||
|
} from '../group/select-group.dialog.component';
|
||||||
|
import {
|
||||||
|
FileUploadItem,
|
||||||
|
CommonApiService
|
||||||
|
} from '@ucap-webmessenger/api-common';
|
||||||
|
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types';
|
||||||
|
import { StatusCode } from '@ucap-webmessenger/api';
|
||||||
|
|
||||||
export interface ProfileDialogData {
|
export interface ProfileDialogData {
|
||||||
userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
|
userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
|
||||||
|
@ -34,8 +51,11 @@ export interface ProfileDialogResult {}
|
||||||
styleUrls: ['./profile.dialog.component.scss']
|
styleUrls: ['./profile.dialog.component.scss']
|
||||||
})
|
})
|
||||||
export class ProfileDialogComponent implements OnInit, OnDestroy {
|
export class ProfileDialogComponent implements OnInit, OnDestroy {
|
||||||
|
userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
|
||||||
loginRes: LoginResponse;
|
loginRes: LoginResponse;
|
||||||
sessionVerinfo: VersionInfo2Response;
|
sessionVerinfo: VersionInfo2Response;
|
||||||
|
environmentsInfo: EnvironmentsInfo;
|
||||||
|
|
||||||
isMe: boolean;
|
isMe: boolean;
|
||||||
isBuddy: boolean;
|
isBuddy: boolean;
|
||||||
isFavorit: boolean;
|
isFavorit: boolean;
|
||||||
|
@ -47,6 +67,8 @@ export class ProfileDialogComponent implements OnInit, OnDestroy {
|
||||||
@Inject(MAT_DIALOG_DATA) public data: ProfileDialogData,
|
@Inject(MAT_DIALOG_DATA) public data: ProfileDialogData,
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
|
private commonApiService: CommonApiService,
|
||||||
|
private snackBarService: SnackBarService,
|
||||||
private store: Store<any>
|
private store: Store<any>
|
||||||
) {
|
) {
|
||||||
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
|
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
|
||||||
|
@ -55,6 +77,11 @@ export class ProfileDialogComponent implements OnInit, OnDestroy {
|
||||||
this.loginRes = this.sessionStorageService.get<LoginResponse>(
|
this.loginRes = this.sessionStorageService.get<LoginResponse>(
|
||||||
KEY_LOGIN_RES_INFO
|
KEY_LOGIN_RES_INFO
|
||||||
);
|
);
|
||||||
|
this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
|
||||||
|
KEY_ENVIRONMENTS_INFO
|
||||||
|
);
|
||||||
|
|
||||||
|
this.userInfo = data.userInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
@ -156,8 +183,68 @@ export class ProfileDialogComponent implements OnInit, OnDestroy {
|
||||||
this.store.dispatch(
|
this.store.dispatch(
|
||||||
SyncStore.delBuddyAndClear({ seq: param.userInfo.seq })
|
SyncStore.delBuddyAndClear({ seq: param.userInfo.seq })
|
||||||
);
|
);
|
||||||
this.isBuddy = false
|
this.isBuddy = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUploadProfileImage(profileImageFileUploadItem: FileUploadItem) {
|
||||||
|
this.commonApiService
|
||||||
|
.fileProfileSave(
|
||||||
|
{
|
||||||
|
userSeq: this.loginRes.userSeq,
|
||||||
|
deviceType: this.environmentsInfo.deviceType,
|
||||||
|
token: this.loginRes.tokenString,
|
||||||
|
file: profileImageFileUploadItem.file,
|
||||||
|
fileUploadItem: profileImageFileUploadItem
|
||||||
|
},
|
||||||
|
this.sessionVerinfo.profileUploadUrl
|
||||||
|
)
|
||||||
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map(res => {
|
||||||
|
if (!res) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StatusCode.Success === res.statusCode) {
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
throw res;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
finalize(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
profileImageFileUploadItem.uploadingProgress$ = undefined;
|
||||||
|
}, 1000);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.subscribe(
|
||||||
|
res => {
|
||||||
|
const userInfo = {
|
||||||
|
...this.loginRes.userInfo,
|
||||||
|
profileImageFile: res.profileSubDir
|
||||||
|
};
|
||||||
|
|
||||||
|
this.store.dispatch(
|
||||||
|
AuthenticationStore.updateLoginRes({
|
||||||
|
loginRes: {
|
||||||
|
...this.loginRes,
|
||||||
|
userInfo
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.userInfo = userInfo as any;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.snackBarService.open(
|
||||||
|
`프로필 이미지 변경중에 문제가 발생하였습니다.`,
|
||||||
|
'',
|
||||||
|
{
|
||||||
|
duration: 3000,
|
||||||
|
verticalPosition: 'bottom'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,3 +113,10 @@ export const userPasswordSetFailure = createAction(
|
||||||
'[Account::Authentication] User Password Set Failure',
|
'[Account::Authentication] User Password Set Failure',
|
||||||
props<{ error: any }>()
|
props<{ error: any }>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const updateLoginRes = createAction(
|
||||||
|
'[Account::Authentication] Update LoginRes',
|
||||||
|
props<{
|
||||||
|
loginRes: LoginResponse;
|
||||||
|
}>()
|
||||||
|
);
|
||||||
|
|
|
@ -5,7 +5,8 @@ import {
|
||||||
increaseLoginFailCount,
|
increaseLoginFailCount,
|
||||||
initialLoginFailCount,
|
initialLoginFailCount,
|
||||||
logout,
|
logout,
|
||||||
logoutInitialize
|
logoutInitialize,
|
||||||
|
updateLoginRes
|
||||||
} from './actions';
|
} from './actions';
|
||||||
|
|
||||||
export const reducer = createReducer(
|
export const reducer = createReducer(
|
||||||
|
@ -17,6 +18,13 @@ export const reducer = createReducer(
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
on(updateLoginRes, (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
loginRes: action.loginRes
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
on(increaseLoginFailCount, (state, action) => {
|
on(increaseLoginFailCount, (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|
|
@ -15,6 +15,39 @@
|
||||||
[path]="userInfo.profileImageFile"
|
[path]="userInfo.profileImageFile"
|
||||||
[default]="'assets/images/img_nophoto_50.png'"
|
[default]="'assets/images/img_nophoto_50.png'"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<mat-spinner
|
||||||
|
*ngIf="
|
||||||
|
profileImageFileUploadItem &&
|
||||||
|
profileImageFileUploadItem.uploadingProgress$
|
||||||
|
"
|
||||||
|
mode="determinate"
|
||||||
|
strokeWidth="5"
|
||||||
|
diameter="84"
|
||||||
|
[value]="profileImageFileUploadItem.uploadingProgress$ | async"
|
||||||
|
class="upload-profile-image-spinner"
|
||||||
|
></mat-spinner>
|
||||||
|
|
||||||
|
<button
|
||||||
|
mat-mini-fab
|
||||||
|
class="mat-elevation-z6 upload-profile-image-btn"
|
||||||
|
*ngIf="isMe"
|
||||||
|
matTooltip="프로필 이미지 변경"
|
||||||
|
matTooltipPosition="above"
|
||||||
|
[disabled]="
|
||||||
|
profileImageFileUploadItem &&
|
||||||
|
profileImageFileUploadItem.uploadingProgress$
|
||||||
|
"
|
||||||
|
(click)="profileImageFileInput.click()"
|
||||||
|
>
|
||||||
|
<span class="mdi mdi-upload mdi-24px"></span>
|
||||||
|
</button>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
#profileImageFileInput
|
||||||
|
style="display: none"
|
||||||
|
(change)="onChangeFileInput()"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="!isMe" class="profile-option">
|
<div *ngIf="!isMe" class="profile-option">
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
::ng-deep .mat-card-header-text{
|
::ng-deep .mat-card-header-text {
|
||||||
width:100%;
|
width: 100%;
|
||||||
.mat-card-subtitle{
|
.mat-card-subtitle {
|
||||||
color: rgb(256, 256, 256, 0.7) !important;
|
color: rgb(256, 256, 256, 0.7) !important;
|
||||||
text-align:center;
|
text-align: center;
|
||||||
margin-top:10px !important;
|
margin-top: 10px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,78 +25,90 @@
|
||||||
width: 400px;
|
width: 400px;
|
||||||
padding: 0 0 20px;
|
padding: 0 0 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
.mat-card-header{
|
.mat-card-header {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
background: #76d9c5;
|
background: #76d9c5;
|
||||||
/*background: linear-gradient(to right, #345385, #ef4c73);*/
|
/*background: linear-gradient(to right, #345385, #ef4c73);*/
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
width:100%;
|
width: 100%;
|
||||||
.mat-card-title{
|
.mat-card-title {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin:0 20px;
|
margin: 0 20px;
|
||||||
span{
|
span {
|
||||||
@include ellipsis(1);
|
@include ellipsis(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.mat-card-content{
|
.mat-card-content {
|
||||||
margin-top:-40px;
|
margin-top: -40px;
|
||||||
.profile-img{
|
.profile-img {
|
||||||
display:flex;
|
display: flex;
|
||||||
height:80px;
|
height: 80px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom:20px;
|
margin-bottom: 20px;
|
||||||
img{
|
img {
|
||||||
widows: 80px;
|
widows: 80px;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color:#efefef;
|
background-color: #efefef;
|
||||||
border:2px solid #ffffff;
|
border: 2px solid #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-profile-image-spinner {
|
||||||
|
position: absolute;
|
||||||
|
top: 90px;
|
||||||
|
left: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-profile-image-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 140px;
|
||||||
|
left: 210px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.profile-option{
|
.profile-option {
|
||||||
display:flex;
|
display: flex;
|
||||||
padding:0 20px;
|
padding: 0 20px;
|
||||||
color:#ffffff;
|
color: #ffffff;
|
||||||
margin-top: -100px;
|
margin-top: -100px;
|
||||||
height: 120px;
|
height: 120px;
|
||||||
.btn-favorite{
|
.btn-favorite {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
.on{
|
.on {
|
||||||
fill:yellow;
|
fill: yellow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.btn-groupadd{
|
.btn-groupadd {
|
||||||
margin-left:auto;
|
margin-left: auto;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
svg{
|
svg {
|
||||||
display:none;
|
display: none;
|
||||||
&.on{
|
&.on {
|
||||||
display:block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ul{
|
ul {
|
||||||
padding:0 20px;
|
padding: 0 20px;
|
||||||
display:flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
margin-top:-20px;
|
margin-top: -20px;
|
||||||
li{
|
li {
|
||||||
display:inline-flex;
|
display: inline-flex;
|
||||||
height:30px;
|
height: 30px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-flow:row;
|
flex-flow: row;
|
||||||
margin-bottom:20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
svg{
|
svg {
|
||||||
margin-right:10px;
|
margin-right: 10px;
|
||||||
color:#777777;
|
color: #777777;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
Input,
|
||||||
|
EventEmitter,
|
||||||
|
Output,
|
||||||
|
ViewChild,
|
||||||
|
ElementRef
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
import { UserInfo } from '@ucap-webmessenger/protocol-sync';
|
import { UserInfo } from '@ucap-webmessenger/protocol-sync';
|
||||||
import {
|
import { UserInfoF } from '@ucap-webmessenger/protocol-query';
|
||||||
UserInfoSS,
|
import { FileUploadItem } from '@ucap-webmessenger/api-common';
|
||||||
UserInfoF,
|
|
||||||
UserInfoDN
|
|
||||||
} from '@ucap-webmessenger/protocol-query';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ucap-profile-profile',
|
selector: 'ucap-profile-profile',
|
||||||
|
@ -37,6 +42,14 @@ export class ProfileComponent implements OnInit {
|
||||||
isBuddy: boolean;
|
isBuddy: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
uploadProfileImage = new EventEmitter<FileUploadItem>();
|
||||||
|
|
||||||
|
@ViewChild('profileImageFileInput', { static: false })
|
||||||
|
profileImageFileInput: ElementRef<HTMLInputElement>;
|
||||||
|
|
||||||
|
profileImageFileUploadItem: FileUploadItem;
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
ngOnInit() {}
|
ngOnInit() {}
|
||||||
|
@ -73,4 +86,14 @@ export class ProfileComponent implements OnInit {
|
||||||
isBuddy: false
|
isBuddy: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChangeFileInput() {
|
||||||
|
this.profileImageFileUploadItem = FileUploadItem.fromFiles(
|
||||||
|
this.profileImageFileInput.nativeElement.files
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
this.uploadProfileImage.emit(this.profileImageFileUploadItem);
|
||||||
|
|
||||||
|
this.profileImageFileInput.nativeElement.value = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
import { MatRippleModule, MatCheckboxModule } from '@angular/material';
|
import { MatRippleModule, MatCheckboxModule } from '@angular/material';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
|
|
||||||
import { UCapUiModule } from '@ucap-webmessenger/ui';
|
import { UCapUiModule } from '@ucap-webmessenger/ui';
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ const SERVICES = [];
|
||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
|
|
||||||
UCapUiModule
|
UCapUiModule
|
||||||
],
|
],
|
||||||
|
|
|
@ -5,15 +5,19 @@ import {
|
||||||
Output,
|
Output,
|
||||||
Input,
|
Input,
|
||||||
AfterViewInit,
|
AfterViewInit,
|
||||||
OnInit
|
OnInit,
|
||||||
|
OnChanges,
|
||||||
|
SimpleChanges
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
|
|
||||||
|
const PATH = 'path';
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: 'img[ucapImage]'
|
selector: 'img[ucapImage]'
|
||||||
})
|
})
|
||||||
export class ImageDirective implements OnInit, AfterViewInit {
|
export class ImageDirective implements OnInit, AfterViewInit, OnChanges {
|
||||||
@Input()
|
@Input()
|
||||||
base: string;
|
base: string;
|
||||||
|
|
||||||
|
@ -50,6 +54,19 @@ export class ImageDirective implements OnInit, AfterViewInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
|
this.loadImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
const pathChanges = changes[PATH];
|
||||||
|
|
||||||
|
if (!!pathChanges && !pathChanges.firstChange) {
|
||||||
|
this.loadImage();
|
||||||
|
this.logger.debug('ucapImage.ngOnChanges', changes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadImage(): void {
|
||||||
if (this.imageSrc === this.default) {
|
if (this.imageSrc === this.default) {
|
||||||
this.elementRef.nativeElement.src = this.default;
|
this.elementRef.nativeElement.src = this.default;
|
||||||
this.loaded.emit(this.elementRef.nativeElement);
|
this.loaded.emit(this.elementRef.nativeElement);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user