This commit is contained in:
richard-loafle 2020-05-08 15:12:26 +09:00
parent c9540517b0
commit 946eed63ed
75 changed files with 4198 additions and 3457 deletions

6451
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -179,13 +179,13 @@
"@ucap/ng-protocol-sync": "file:pack/ucap-ng-protocol-sync-0.0.3.tgz", "@ucap/ng-protocol-sync": "file:pack/ucap-ng-protocol-sync-0.0.3.tgz",
"@ucap/ng-protocol-umg": "file:pack/ucap-ng-protocol-umg-0.0.3.tgz", "@ucap/ng-protocol-umg": "file:pack/ucap-ng-protocol-umg-0.0.3.tgz",
"@ucap/ng-store-authentication": "file:pack/ucap-ng-store-authentication-0.0.10.tgz", "@ucap/ng-store-authentication": "file:pack/ucap-ng-store-authentication-0.0.10.tgz",
"@ucap/ng-store-chat": "file:pack/ucap-ng-store-chat-0.0.5.tgz", "@ucap/ng-store-chat": "file:pack/ucap-ng-store-chat-0.0.6.tgz",
"@ucap/ng-store-group": "file:pack/ucap-ng-store-group-0.0.6.tgz", "@ucap/ng-store-group": "file:pack/ucap-ng-store-group-0.0.7.tgz",
"@ucap/ng-store-organization": "file:pack/ucap-ng-store-organization-0.0.4.tgz", "@ucap/ng-store-organization": "file:pack/ucap-ng-store-organization-0.0.4.tgz",
"@ucap/ng-ui": "file:pack/ucap-ng-ui-0.0.4.tgz", "@ucap/ng-ui": "file:pack/ucap-ng-ui-0.0.7.tgz",
"@ucap/ng-ui-authentication": "file:pack/ucap-ng-ui-authentication-0.0.16.tgz", "@ucap/ng-ui-authentication": "file:pack/ucap-ng-ui-authentication-0.0.19.tgz",
"@ucap/ng-ui-group": "file:pack/ucap-ng-ui-group-0.0.3.tgz", "@ucap/ng-ui-group": "file:pack/ucap-ng-ui-group-0.0.28.tgz",
"@ucap/ng-ui-organization": "file:pack/ucap-ng-ui-organization-0.0.2.tgz", "@ucap/ng-ui-organization": "file:pack/ucap-ng-ui-organization-0.0.15.tgz",
"@ucap/ng-ui-skin-default": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz", "@ucap/ng-ui-skin-default": "file:pack/ucap-ng-ui-skin-default-0.0.1.tgz",
"@ucap/ng-web-socket": "file:pack/ucap-ng-web-socket-0.0.2.tgz", "@ucap/ng-web-socket": "file:pack/ucap-ng-web-socket-0.0.2.tgz",
"@ucap/ng-web-storage": "file:pack/ucap-ng-web-storage-0.0.3.tgz", "@ucap/ng-web-storage": "file:pack/ucap-ng-web-storage-0.0.3.tgz",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-api-common", "name": "@ucap/ng-api-common",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-api-external", "name": "@ucap/ng-api-external",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-api-message", "name": "@ucap/ng-api-message",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-api-prompt", "name": "@ucap/ng-api-prompt",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-api-public", "name": "@ucap/ng-api-public",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-core", "name": "@ucap/ng-core",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-i18n", "name": "@ucap/ng-i18n",
"version": "0.0.6", "version": "0.0.6",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.6", "@angular/common": "^9.0.6",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-logger", "name": "@ucap/ng-logger",
"version": "0.0.2", "version": "0.0.2",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.1.0", "@angular/common": "^9.1.0",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-native-browser", "name": "@ucap/ng-native-browser",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-native", "name": "@ucap/ng-native",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-pi", "name": "@ucap/ng-pi",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-authentication", "name": "@ucap/ng-protocol-authentication",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-buddy", "name": "@ucap/ng-protocol-buddy",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-event", "name": "@ucap/ng-protocol-event",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-file", "name": "@ucap/ng-protocol-file",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-group", "name": "@ucap/ng-protocol-group",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-info", "name": "@ucap/ng-protocol-info",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-inner", "name": "@ucap/ng-protocol-inner",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-option", "name": "@ucap/ng-protocol-option",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-ping", "name": "@ucap/ng-protocol-ping",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-query", "name": "@ucap/ng-protocol-query",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-room", "name": "@ucap/ng-protocol-room",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-service", "name": "@ucap/ng-protocol-service",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-status", "name": "@ucap/ng-protocol-status",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-sync", "name": "@ucap/ng-protocol-sync",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol-umg", "name": "@ucap/ng-protocol-umg",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-protocol", "name": "@ucap/ng-protocol",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-store-authentication", "name": "@ucap/ng-store-authentication",
"version": "0.0.10", "version": "0.0.10",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -1,8 +1,8 @@
{ {
"name": "@ucap/ng-store-chat", "name": "@ucap/ng-store-chat",
"version": "0.0.5", "version": "0.0.6",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -20,7 +20,8 @@ import {
ExitForcingRequest, ExitForcingRequest,
ExitForcingResponse, ExitForcingResponse,
UpdateTimerSetRequest, UpdateTimerSetRequest,
UpdateTimerSetResponse UpdateTimerSetResponse,
UserInfoShort
} from '@ucap/protocol-room'; } from '@ucap/protocol-room';
/** /**
@ -32,6 +33,7 @@ export const rooms = createAction(
); );
/** /**
* Success of rooms request * Success of rooms request
* RoomUserData is detail type.
*/ */
export const roomsSuccess = createAction( export const roomsSuccess = createAction(
'[ucap::chat::room] rooms Success', '[ucap::chat::room] rooms Success',
@ -51,6 +53,31 @@ export const roomsFailure = createAction(
props<{ error: any }>() props<{ error: any }>()
); );
/**
* Success of rooms2 request
* RoomUserData is detail, short type both.
*/
export const rooms2Success = createAction(
'[ucap::chat::room] rooms2 Success',
props<{
roomList: RoomInfo[];
roomUserInfoMap: {
[param: string]: {
userInfoShortList: UserInfoShort[];
userInfoList: RoomUserInfo[];
};
};
syncDate: string;
}>()
);
/**
* Failure of rooms2 request
*/
export const rooms2Failure = createAction(
'[ucap::chat::room] rooms2 Failure',
props<{ error: any }>()
);
/** /**
* retrieve room information and list of user information * retrieve room information and list of user information
*/ */

View File

@ -67,7 +67,9 @@ import {
expelFailure, expelFailure,
updateTimeRoomInterval, updateTimeRoomInterval,
updateTimeRoomIntervalSuccess, updateTimeRoomIntervalSuccess,
updateTimeRoomIntervalFailure updateTimeRoomIntervalFailure,
rooms2Success,
rooms2Failure
} from './actions'; } from './actions';
@Injectable() @Injectable()
@ -75,7 +77,7 @@ export class Effects {
sessionCreatedForRooms$ = createEffect(() => { sessionCreatedForRooms$ = createEffect(() => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(LoginActions.sessionCreated), ofType(LoginActions.sessionCreated),
map(action => rooms({ localeCode: action.loginSession.localeCode })) map((action) => rooms({ localeCode: action.loginSession.localeCode }))
); );
}); });
@ -84,17 +86,32 @@ export class Effects {
ofType(rooms), ofType(rooms),
withLatestFrom(this.store.pipe(select(RoomSelector.roomsSyncDate))), withLatestFrom(this.store.pipe(select(RoomSelector.roomsSyncDate))),
switchMap(([action, syncDate]) => { switchMap(([action, syncDate]) => {
// // CASE :: RoomUser Data 중 Detail data 만 수집.
// return this.syncProtocolService
// .room({ syncDate, localeCode: action.localeCode })
// .pipe(
// map((res) => {
// return roomsSuccess({
// roomList: res.roomList,
// roomUserInfoMap: res.roomUserInfoMap,
// syncDate: res.res.syncDate
// });
// }),
// catchError((error) => of(roomsFailure({ error })))
// );
// CASE :: RoomUser Data 중 Detail data, Short data 수집.
return this.syncProtocolService return this.syncProtocolService
.room({ syncDate, localeCode: action.localeCode }) .room2({ syncDate, localeCode: action.localeCode })
.pipe( .pipe(
map(res => map((res) => {
roomsSuccess({ return rooms2Success({
roomList: res.roomList, roomList: res.roomList,
roomUserInfoMap: res.roomUserInfoMap, roomUserInfoMap: res.roomUserInfoMap,
syncDate: res.res.syncDate syncDate: res.res.syncDate
}) });
), }),
catchError(error => of(roomsFailure({ error }))) catchError((error) => of(rooms2Failure({ error })))
); );
}) })
); );
@ -103,16 +120,16 @@ export class Effects {
room$ = createEffect(() => { room$ = createEffect(() => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(room), ofType(room),
map(action => action.req), map((action) => action.req),
switchMap(req => { switchMap((req) => {
return this.roomProtocolService.info(req).pipe( return this.roomProtocolService.info(req).pipe(
map(res => map((res) =>
roomSuccess({ roomSuccess({
roomInfo: res.roomInfo, roomInfo: res.roomInfo,
userInfoList: res.userInfoList userInfoList: res.userInfoList
}) })
), ),
catchError(error => of(roomFailure({ error }))) catchError((error) => of(roomFailure({ error })))
); );
}) })
); );
@ -121,13 +138,13 @@ export class Effects {
create$ = createEffect(() => create$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(create), ofType(create),
map(action => action.req), map((action) => action.req),
exhaustMap(req => { exhaustMap((req) => {
return this.roomProtocolService.open(req).pipe( return this.roomProtocolService.open(req).pipe(
map((res: CreateResponse) => { map((res: CreateResponse) => {
return createSuccess({ res }); return createSuccess({ res });
}), }),
catchError(error => of(createFailure({ error }))) catchError((error) => of(createFailure({ error })))
); );
}) })
) )
@ -136,13 +153,13 @@ export class Effects {
createTimer$ = createEffect(() => createTimer$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(createTimer), ofType(createTimer),
map(action => action.req), map((action) => action.req),
exhaustMap(req => { exhaustMap((req) => {
return this.roomProtocolService.open3(req).pipe( return this.roomProtocolService.open3(req).pipe(
map((res: CreateTimerResponse) => { map((res: CreateTimerResponse) => {
return createTimerSuccess({ res }); return createTimerSuccess({ res });
}), }),
catchError(error => of(createTimerFailure({ error }))) catchError((error) => of(createTimerFailure({ error })))
); );
}) })
) )
@ -151,14 +168,14 @@ export class Effects {
del$ = createEffect(() => del$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(del), ofType(del),
map(action => action.req), map((action) => action.req),
exhaustMap(req => { exhaustMap((req) => {
return this.roomProtocolService.exit(req).pipe( return this.roomProtocolService.exit(req).pipe(
switchMap((res: DeleteResponse) => [ switchMap((res: DeleteResponse) => [
close({ roomIds: [res.roomId] }), close({ roomIds: [res.roomId] }),
delSuccess({ res }) delSuccess({ res })
]), ]),
catchError(error => of(delFailure({ error }))) catchError((error) => of(delFailure({ error })))
); );
}) })
) )
@ -167,13 +184,13 @@ export class Effects {
update$ = createEffect(() => update$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(update), ofType(update),
map(action => action.req), map((action) => action.req),
exhaustMap(req => { exhaustMap((req) => {
return this.roomProtocolService.update(req).pipe( return this.roomProtocolService.update(req).pipe(
map((res: UpdateResponse) => { map((res: UpdateResponse) => {
return updateSuccess({ res }); return updateSuccess({ res });
}), }),
catchError(error => of(updateFailure({ error }))) catchError((error) => of(updateFailure({ error })))
); );
}) })
) )
@ -182,7 +199,7 @@ export class Effects {
excludeUser$ = createEffect(() => { excludeUser$ = createEffect(() => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(excludeUser), ofType(excludeUser),
map(action => map((action) =>
excludeUserSuccess({ excludeUserSuccess({
roomId: action.roomId, roomId: action.roomId,
userSeqs: action.userSeqs userSeqs: action.userSeqs
@ -194,21 +211,21 @@ export class Effects {
open$ = createEffect(() => { open$ = createEffect(() => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(open), ofType(open),
map(action => openSuccess({ roomIds: [...action.roomIds] })) map((action) => openSuccess({ roomIds: [...action.roomIds] }))
); );
}); });
close$ = createEffect(() => { close$ = createEffect(() => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(close), ofType(close),
map(action => closeSuccess({ roomIds: [...action.roomIds] })) map((action) => closeSuccess({ roomIds: [...action.roomIds] }))
); );
}); });
inviteOrCreate$ = createEffect(() => inviteOrCreate$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(inviteOrCreate), ofType(inviteOrCreate),
map(action => { map((action) => {
const roomInfo = action.roomInfo; const roomInfo = action.roomInfo;
const localeCode = action.localeCode; const localeCode = action.localeCode;
@ -235,7 +252,7 @@ export class Effects {
invite$ = createEffect(() => invite$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(invite), ofType(invite),
exhaustMap(action => { exhaustMap((action) => {
const req = action.req; const req = action.req;
const localeCode = action.localeCode; const localeCode = action.localeCode;
@ -252,7 +269,7 @@ export class Effects {
}) })
]; ];
}), }),
catchError(error => of(inviteFailure({ error }))) catchError((error) => of(inviteFailure({ error })))
); );
}) })
) )
@ -261,13 +278,13 @@ export class Effects {
expel$ = createEffect(() => expel$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(expel), ofType(expel),
map(action => action.req), map((action) => action.req),
exhaustMap(req => { exhaustMap((req) => {
return this.roomProtocolService.exitForcing(req).pipe( return this.roomProtocolService.exitForcing(req).pipe(
map((res: ExitForcingResponse) => { map((res: ExitForcingResponse) => {
return expelSuccess({ res }); return expelSuccess({ res });
}), }),
catchError(error => of(expelFailure({ error }))) catchError((error) => of(expelFailure({ error })))
); );
}) })
) )
@ -276,13 +293,13 @@ export class Effects {
updateTimeRoomInterval$ = createEffect(() => updateTimeRoomInterval$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(updateTimeRoomInterval), ofType(updateTimeRoomInterval),
map(action => action.req), map((action) => action.req),
exhaustMap(req => { exhaustMap((req) => {
return this.roomProtocolService.updateTimerSet(req).pipe( return this.roomProtocolService.updateTimerSet(req).pipe(
map((res: UpdateTimerSetResponse) => { map((res: UpdateTimerSetResponse) => {
return updateTimeRoomIntervalSuccess({ res }); return updateTimeRoomIntervalSuccess({ res });
}), }),
catchError(error => of(updateTimeRoomIntervalFailure({ error }))) catchError((error) => of(updateTimeRoomIntervalFailure({ error })))
); );
}) })
) )
@ -291,7 +308,7 @@ export class Effects {
inviteNotification$ = createEffect(() => { inviteNotification$ = createEffect(() => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(inviteNotification), ofType(inviteNotification),
map(action => map((action) =>
room({ room({
req: { req: {
roomId: action.noti.roomId, roomId: action.noti.roomId,
@ -306,7 +323,7 @@ export class Effects {
exitNotification$ = createEffect(() => { exitNotification$ = createEffect(() => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(exitNotification), ofType(exitNotification),
switchMap(action => { switchMap((action) => {
if (action.userSeq === action.senderSeq) { if (action.userSeq === action.senderSeq) {
return [ return [
close({ roomIds: [action.roomId] }), close({ roomIds: [action.roomId] }),

View File

@ -8,14 +8,17 @@ import {
initialState, initialState,
adapterRoom, adapterRoom,
adapterRoomUser, adapterRoomUser,
RoomUserMap RoomUserMap,
RoomUserShortMap,
adapterRoomUserShort
} from './state'; } from './state';
import { import {
roomsSuccess, roomsSuccess,
roomSuccess, roomSuccess,
excludeUser, excludeUser,
excludeUserSuccess, excludeUserSuccess,
delSuccess delSuccess,
rooms2Success
} from './actions'; } from './actions';
export const reducer = createReducer( export const reducer = createReducer(
@ -40,7 +43,7 @@ export const reducer = createReducer(
const value = state.rooms.entities[key]; const value = state.rooms.entities[key];
unreadTotal += isNaN(value.noReadCnt) ? 0 : value.noReadCnt; unreadTotal += isNaN(value.noReadCnt) ? 0 : value.noReadCnt;
} }
action.roomList.map(item => (unreadTotal += item.noReadCnt)); action.roomList.map((item) => (unreadTotal += item.noReadCnt));
return { return {
...state, ...state,
@ -55,6 +58,53 @@ export const reducer = createReducer(
}; };
}), }),
on(rooms2Success, (state, action) => {
const roomUserMapList: RoomUserMap[] = [];
const roomUserShortMapList: RoomUserShortMap[] = [];
for (const key in action.roomUserInfoMap) {
if (action.roomUserInfoMap.hasOwnProperty(key)) {
const userInfosMap = action.roomUserInfoMap[key];
if (!!userInfosMap && 0 < userInfosMap.userInfoList.length) {
roomUserMapList.push({
roomId: key,
userInfos: userInfosMap.userInfoList
});
}
if (!!userInfosMap && 0 < userInfosMap.userInfoShortList.length) {
roomUserShortMapList.push({
roomId: key,
userInfos: userInfosMap.userInfoShortList
});
}
}
}
let unreadTotal = 0;
// tslint:disable-next-line: forin
for (const key in state.rooms.entities) {
const value = state.rooms.entities[key];
unreadTotal += isNaN(value.noReadCnt) ? 0 : value.noReadCnt;
}
action.roomList.map((item) => (unreadTotal += item.noReadCnt));
return {
...state,
rooms: adapterRoom.upsertMany(action.roomList, {
...state.rooms,
syncDate: action.syncDate
}),
roomUsers: adapterRoomUser.upsertMany(roomUserMapList, {
...state.roomUsers
}),
roomUsersShort: adapterRoomUserShort.upsertMany(roomUserShortMapList, {
...state.roomUsersShort
}),
unreadTotal
};
}),
on(roomSuccess, (state, action) => { on(roomSuccess, (state, action) => {
const roomUserMapList: RoomUserMap[] = []; const roomUserMapList: RoomUserMap[] = [];
@ -85,9 +135,9 @@ export const reducer = createReducer(
const userInfos: RoomUserInfo[] = [...roomUserMap.userInfos]; const userInfos: RoomUserInfo[] = [...roomUserMap.userInfos];
action.userSeqs.forEach(userSeq => { action.userSeqs.forEach((userSeq) => {
const userInfo: RoomUserInfo = userInfos.find( const userInfo: RoomUserInfo = userInfos.find(
u => userSeq === String(u.seq) (u) => userSeq === String(u.seq)
); );
if (!!userInfo && !!userInfo.seq) { if (!!userInfo && !!userInfo.seq) {

View File

@ -3,22 +3,22 @@ import moment from 'moment';
import { Selector, createSelector } from '@ngrx/store'; import { Selector, createSelector } from '@ngrx/store';
import { EntityState, createEntityAdapter, Dictionary } from '@ngrx/entity'; import { EntityState, createEntityAdapter, Dictionary } from '@ngrx/entity';
import { RoomUserDetailData } from '@ucap/protocol-sync'; import { RoomUserDetailData, RoomUserData } from '@ucap/protocol-sync';
import { RoomInfo, UserInfo as RoomUserInfo } from '@ucap/protocol-room'; import {
RoomInfo,
UserInfo as RoomUserInfo,
UserInfoShort
} from '@ucap/protocol-room';
export interface RoomState extends EntityState<RoomInfo> { export interface RoomState extends EntityState<RoomInfo> {
syncDate: string; syncDate: string;
} }
export const adapterRoom = createEntityAdapter<RoomInfo>({ export const adapterRoom = createEntityAdapter<RoomInfo>({
selectId: roomInfo => roomInfo.roomId, selectId: (roomInfo) => roomInfo.roomId,
sortComparer: (a, b) => { sortComparer: (a, b) => {
return ( return (
moment(b.finalEventDate) moment(b.finalEventDate).toDate().getTime() -
.toDate() moment(a.finalEventDate).toDate().getTime()
.getTime() -
moment(a.finalEventDate)
.toDate()
.getTime()
); );
} }
}); });
@ -28,24 +28,39 @@ export interface RoomUserMap {
userInfos: RoomUserInfo[]; userInfos: RoomUserInfo[];
} }
export interface RoomUserShortMap {
roomId: string;
userInfos: UserInfoShort[];
}
export interface RoomUserState extends EntityState<RoomUserMap> {} export interface RoomUserState extends EntityState<RoomUserMap> {}
export const adapterRoomUser = createEntityAdapter<RoomUserMap>({ export const adapterRoomUser = createEntityAdapter<RoomUserMap>({
selectId: roomUserDetailData => roomUserDetailData.roomId selectId: (roomUserDetailData) => roomUserDetailData.roomId
});
export interface RoomUserShortState extends EntityState<RoomUserShortMap> {}
export const adapterRoomUserShort = createEntityAdapter<RoomUserShortMap>({
selectId: (roomUserShortData) => roomUserShortData.roomId
}); });
export interface State { export interface State {
rooms: RoomState; rooms: RoomState;
roomUsers: RoomUserState; roomUsers: RoomUserState;
roomUsersShort: RoomUserShortState;
} }
const roomInitialState: RoomState = adapterRoom.getInitialState({ const roomInitialState: RoomState = adapterRoom.getInitialState({
syncDate: '' syncDate: ''
}); });
const roomUserInitialState: RoomUserState = adapterRoomUser.getInitialState({}); const roomUserInitialState: RoomUserState = adapterRoomUser.getInitialState({});
const roomUserShortInitialState: RoomUserShortState = adapterRoomUserShort.getInitialState(
{}
);
export const initialState: State = { export const initialState: State = {
rooms: roomInitialState, rooms: roomInitialState,
roomUsers: roomUserInitialState roomUsers: roomUserInitialState,
roomUsersShort: roomUserShortInitialState
}; };
const { const {
@ -62,6 +77,13 @@ const {
selectTotal: selectTotalForRoomUser selectTotal: selectTotalForRoomUser
} = adapterRoomUser.getSelectors(); } = adapterRoomUser.getSelectors();
const {
selectAll: selectAllForRoomUserShort,
selectEntities: selectEntitiesForRoomUserShort,
selectIds: selectIdsForRoomUserShort,
selectTotal: selectTotalForRoomUserShort
} = adapterRoomUserShort.getSelectors();
export function selectors<S>(selector: Selector<any, State>) { export function selectors<S>(selector: Selector<any, State>) {
const selectRooms = createSelector(selector, (state: State) => state.rooms); const selectRooms = createSelector(selector, (state: State) => state.rooms);
@ -70,6 +92,11 @@ export function selectors<S>(selector: Selector<any, State>) {
(state: State) => state.roomUsers (state: State) => state.roomUsers
); );
const selectRoomUsersShort = createSelector(
selector,
(state: State) => state.roomUsersShort
);
return { return {
rooms: createSelector(selectRooms, selectAllForRoom), rooms: createSelector(selectRooms, selectAllForRoom),
room: createSelector( room: createSelector(
@ -78,7 +105,10 @@ export function selectors<S>(selector: Selector<any, State>) {
(roomState: RoomState, entities: Dictionary<RoomInfo>, roomId: string) => (roomState: RoomState, entities: Dictionary<RoomInfo>, roomId: string) =>
entities && entities[roomId] entities && entities[roomId]
), ),
roomsSyncDate: createSelector(selectRooms, roomState => roomState.syncDate), roomsSyncDate: createSelector(
selectRooms,
(roomState) => roomState.syncDate
),
roomUsers: createSelector(selectRoomUsers, selectAllForRoomUser), roomUsers: createSelector(selectRoomUsers, selectAllForRoomUser),
roomUser: createSelector( roomUser: createSelector(
selectRoomUsers, selectRoomUsers,
@ -89,6 +119,19 @@ export function selectors<S>(selector: Selector<any, State>) {
roomId: string roomId: string
) => entities && entities[roomId] ) => entities && entities[roomId]
), ),
roomUsersShort: createSelector(
selectRoomUsersShort,
selectAllForRoomUserShort
),
roomUserShort: createSelector(
selectRoomUsersShort,
selectEntitiesForRoomUserShort,
(
roomUserShortState: RoomUserShortState,
entities: Dictionary<RoomUserData>,
roomId: string
) => entities && entities[roomId]
),
unreadTotal: createSelector( unreadTotal: createSelector(
selectRooms, selectRooms,
selectAllForRoom, selectAllForRoom,

View File

@ -1,8 +1,8 @@
{ {
"name": "@ucap/ng-store-group", "name": "@ucap/ng-store-group",
"version": "0.0.6", "version": "0.0.7",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -31,7 +31,7 @@ import { _MODULE_CONFIG } from '../../config/token';
import * as buddyActions from '../buddy/actions'; import * as buddyActions from '../buddy/actions';
import { GroupSelector } from '../state'; import { GroupSelector, BuddySelector } from '../state';
import { import {
groups, groups,
@ -57,7 +57,7 @@ export class Effects {
sessionCreatedForGroups$ = createEffect(() => { sessionCreatedForGroups$ = createEffect(() => {
return this.actions$.pipe( return this.actions$.pipe(
ofType(LoginActions.sessionCreated), ofType(LoginActions.sessionCreated),
map(action => groups()) map((action) => groups())
); );
}); });
@ -67,13 +67,13 @@ export class Effects {
withLatestFrom(this.store.pipe(select(GroupSelector.groupSyncDate))), withLatestFrom(this.store.pipe(select(GroupSelector.groupSyncDate))),
switchMap(([action, syncDate]) => { switchMap(([action, syncDate]) => {
return this.syncProtocolService.group2({ syncDate }).pipe( return this.syncProtocolService.group2({ syncDate }).pipe(
map(res => map((res) =>
groupsSuccess({ groupsSuccess({
groupList: res.groupInfos, groupList: res.groupInfos,
syncDate: res.res.syncDate syncDate: res.res.syncDate
}) })
), ),
catchError(error => of(groupsFailure({ error }))) catchError((error) => of(groupsFailure({ error })))
); );
}) })
); );
@ -82,7 +82,8 @@ export class Effects {
create$ = createEffect(() => create$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(create), ofType(create),
exhaustMap(action => { withLatestFrom(this.store.pipe(select(BuddySelector.buddies))),
exhaustMap(([action, buddies]) => {
return this.groupProtocolService return this.groupProtocolService
.add({ .add({
groupName: action.groupName groupName: action.groupName
@ -92,6 +93,19 @@ export class Effects {
const actions: any[] = []; const actions: any[] = [];
if (!!action.targetUserSeqs && 0 < action.targetUserSeqs.length) { if (!!action.targetUserSeqs && 0 < action.targetUserSeqs.length) {
const addBuddies: number[] = [];
action.targetUserSeqs.forEach((item) => {
if (!buddies[item]) {
addBuddies.push(Number(item));
}
});
if (addBuddies.length > 0) {
actions.push(
buddyActions.add({
req: { userSeqs: action.targetUserSeqs }
})
);
}
actions.push( actions.push(
update({ update({
req: { req: {
@ -108,7 +122,7 @@ export class Effects {
return actions; return actions;
}), }),
catchError(error => of(createFailure({ error }))) catchError((error) => of(createFailure({ error })))
); );
}) })
) )
@ -128,7 +142,7 @@ export class Effects {
// Del Buddy // Del Buddy
let userSeqsForDelete: string[] = targetGroup.userSeqs.filter( let userSeqsForDelete: string[] = targetGroup.userSeqs.filter(
v => targetUserSeqs.indexOf(v) < 0 (v) => targetUserSeqs.indexOf(v) < 0
); );
// 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다. // 소속부서(내부서) 고정그룹 사용시 소속부서원을 삭제하지 않는다.
@ -137,18 +151,18 @@ export class Effects {
this.moduleConfig.useMyDeptGroup this.moduleConfig.useMyDeptGroup
) { ) {
userSeqsForDelete = userSeqsForDelete.filter( userSeqsForDelete = userSeqsForDelete.filter(
delbuddy => (delbuddy) =>
myDeptUserList.filter(deptUser => deptUser.seq === delbuddy) myDeptUserList.filter((deptUser) => deptUser.seq === delbuddy)
.length === 0 .length === 0
); );
} }
userSeqsForDelete = userSeqsForDelete.filter(delbuddy => { userSeqsForDelete = userSeqsForDelete.filter((delbuddy) => {
let exist = false; let exist = false;
for (const group of groupList) { for (const group of groupList) {
if ( if (
group.seq !== targetGroup.seq && group.seq !== targetGroup.seq &&
group.userSeqs.filter(v => v === delbuddy).length > 0 group.userSeqs.filter((v) => v === delbuddy).length > 0
) { ) {
exist = true; exist = true;
break; break;
@ -184,10 +198,10 @@ export class Effects {
withLatestFrom(this.store.pipe(select(GroupSelector.groups))), withLatestFrom(this.store.pipe(select(GroupSelector.groups))),
exhaustMap(([action, groupList]) => { exhaustMap(([action, groupList]) => {
// copy to // copy to
const toGroup = groupList.find(g => g.seq === action.toGroup.seq); const toGroup = groupList.find((g) => g.seq === action.toGroup.seq);
let toTrgtUserSeqs = toGroup.userSeqs; let toTrgtUserSeqs = toGroup.userSeqs;
action.targetUserSeq.forEach(trgtSeq => { action.targetUserSeq.forEach((trgtSeq) => {
if (toTrgtUserSeqs.indexOf(trgtSeq) > -1) { if (toTrgtUserSeqs.indexOf(trgtSeq) > -1) {
// ignore // ignore
} else { } else {
@ -205,7 +219,7 @@ export class Effects {
exhaustMap((resTo: GroupUpdateResponse) => { exhaustMap((resTo: GroupUpdateResponse) => {
// del from // del from
const fromGroup = groupList.find( const fromGroup = groupList.find(
g => g.seq === action.fromGroup.seq (g) => g.seq === action.fromGroup.seq
); );
const fromTrgtUserSeqs = fromGroup.userSeqs; const fromTrgtUserSeqs = fromGroup.userSeqs;
@ -215,17 +229,17 @@ export class Effects {
groupSeq: action.fromGroup.seq, groupSeq: action.fromGroup.seq,
groupName: action.fromGroup.name, groupName: action.fromGroup.name,
userSeqs: fromTrgtUserSeqs.filter( userSeqs: fromTrgtUserSeqs.filter(
trgtSeq => action.targetUserSeq.indexOf(trgtSeq) < 0 (trgtSeq) => action.targetUserSeq.indexOf(trgtSeq) < 0
) )
}) })
.pipe( .pipe(
map((resFrom: GroupUpdateResponse) => { map((resFrom: GroupUpdateResponse) => {
return groups(); return groups();
}), }),
catchError(error => of(moveFromFailure({ error }))) catchError((error) => of(moveFromFailure({ error })))
); );
}), }),
catchError(error => of(moveToFailure({ error }))) catchError((error) => of(moveToFailure({ error })))
); );
}) })
) )
@ -249,18 +263,18 @@ export class Effects {
this.moduleConfig.useMyDeptGroup this.moduleConfig.useMyDeptGroup
) { ) {
userSeqsForDelete = targetUserSeqs.filter( userSeqsForDelete = targetUserSeqs.filter(
delbuddy => (delbuddy) =>
myDeptUserList.filter(deptUser => deptUser.seq === delbuddy) myDeptUserList.filter((deptUser) => deptUser.seq === delbuddy)
.length === 0 .length === 0
); );
} }
userSeqsForDelete = targetUserSeqs.filter(delbuddy => { userSeqsForDelete = targetUserSeqs.filter((delbuddy) => {
let exist = false; let exist = false;
for (const group of groupList) { for (const group of groupList) {
if ( if (
group.seq !== action.group.seq && group.seq !== action.group.seq &&
group.userSeqs.filter(v => v === delbuddy).length > 0 group.userSeqs.filter((v) => v === delbuddy).length > 0
) { ) {
exist = true; exist = true;
break; break;
@ -271,7 +285,7 @@ export class Effects {
if (userSeqsForDelete.length > 0) { if (userSeqsForDelete.length > 0) {
// 즐겨찾기 해제. // 즐겨찾기 해제.
userSeqsForDelete.forEach(buddySeq => { userSeqsForDelete.forEach((buddySeq) => {
this.store.dispatch( this.store.dispatch(
buddyActions.update({ buddyActions.update({
req: { req: {
@ -296,7 +310,7 @@ export class Effects {
map((res: GroupDelResponse) => { map((res: GroupDelResponse) => {
return delSuccess({ res }); return delSuccess({ res });
}), }),
catchError(error => of(delFailure({ error }))) catchError((error) => of(delFailure({ error })))
); );
}) })
) )
@ -305,13 +319,13 @@ export class Effects {
update$ = createEffect(() => update$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(update), ofType(update),
map(action => action.req), map((action) => action.req),
concatMap(req => concatMap((req) =>
this.groupProtocolService.update2(req).pipe( this.groupProtocolService.update2(req).pipe(
map((res: GroupUpdateResponse) => { map((res: GroupUpdateResponse) => {
return groups(); return groups();
}), }),
catchError(error => of(updateFailure({ error }))) catchError((error) => of(updateFailure({ error })))
) )
) )
) )

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-store-organization", "name": "@ucap/ng-store-organization",
"version": "0.0.4", "version": "0.0.4",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.0", "@angular/common": "^9.0.0",

View File

@ -1,8 +1,8 @@
{ {
"name": "@ucap/ng-ui-authentication", "name": "@ucap/ng-ui-authentication",
"version": "0.0.16", "version": "0.0.19",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/cdk": "^9.0.0", "@angular/cdk": "^9.0.0",

View File

@ -10,17 +10,18 @@
<mat-select <mat-select
[formControl]="companyCodeFormControl" [formControl]="companyCodeFormControl"
[value]="companyCode || fixedCompanyCode" [value]="companyCode || fixedCompanyCode"
placeholder="{{ 'login.labels.selectCompany' | ucapI18n }}"
> >
<mat-option <mat-option
*ngFor="let company of companyList" *ngFor="let company of companyList"
[value]="company.companyCode" [value]="company.companyCode"
>{{ company.companyName }} >
{{ company.companyName }}
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<div class="input-lineless"> <div class="input-lineless">
12345
<!--<span class="icon-img"><i class="mid mdi-account-tie-outline"></i></span>--> <!--<span class="icon-img"><i class="mid mdi-account-tie-outline"></i></span>-->
<span class="icon-img"> <span class="icon-img">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20.82 22"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20.82 22">

View File

@ -4,6 +4,7 @@
"lib": { "lib": {
"entryFile": "src/public-api.ts", "entryFile": "src/public-api.ts",
"umdModuleIds": { "umdModuleIds": {
"ngx-perfect-scrollbar": "ngx-perfect-scrollbar",
"@ucap/core": "@ucap/core", "@ucap/core": "@ucap/core",
"@ucap/ng-ui": "@ucap/ng-ui" "@ucap/ng-ui": "@ucap/ng-ui"
} }

View File

@ -1,8 +1,8 @@
{ {
"name": "@ucap/ng-ui-group", "name": "@ucap/ng-ui-group",
"version": "0.0.3", "version": "0.0.28",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/cdk": "^9.0.0", "@angular/cdk": "^9.0.0",

View File

@ -1,16 +0,0 @@
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
import { ExpansionListComponent } from './expansion-list.component';
export default {
title: 'ExpansionListComponent',
component: ExpansionListComponent
};
export const Text = () => ({
component: ExpansionListComponent,
props: {
text: 'Hello ExpansionListComponent'
}
});

View File

@ -1,12 +1,10 @@
<div> <div class="ucap-group-expansion-container" fxFlexFill>
<cdk-virtual-scroll-viewport <cdk-virtual-scroll-viewport #cvsvList perfectScrollbar fxFlexFill>
#cvsvList
perfectScrollbar
fxFlexFill
virtualScrollStrategy="virtualScrollStrategy"
>
<ng-container <ng-container
*cdkVirtualFor="let node of dataSource.expandedData$" *cdkVirtualFor="
let node of dataSource.expandedData$;
templateCacheSize: 0
"
></ng-container> ></ng-container>
<mat-tree #treeList [dataSource]="dataSource" [treeControl]="treeControl"> <mat-tree #treeList [dataSource]="dataSource" [treeControl]="treeControl">
@ -18,7 +16,8 @@
<li> <li>
<div> <div>
<ng-container <ng-container
ngTemplateOutlet="nodeTemplate; context: {$implicit: node}" [ngTemplateOutlet]="nodeTemplate"
[ngTemplateOutletContext]="{ $implicit: node?.node }"
></ng-container> ></ng-container>
</div> </div>
</li> </li>
@ -48,17 +47,20 @@
<ng-container [ngSwitch]="node.nodeType"> <ng-container [ngSwitch]="node.nodeType">
<ng-container <ng-container
*ngSwitchCase="NodeType.Favorite" *ngSwitchCase="NodeType.Favorite"
ngTemplateOutlet="favoriteHeaderTemplate; context: {$implicit: node}" [ngTemplateOutlet]="favoriteHeaderTemplate"
[ngTemplateOutletContext]="{ $implicit: node?.node }"
> >
</ng-container> </ng-container>
<ng-container <ng-container
*ngSwitchCase="NodeType.Default" *ngSwitchCase="NodeType.Default"
ngTemplateOutlet="defaultHeaderTemplate; context: {$implicit: node}" [ngTemplateOutlet]="defaultHeaderTemplate"
[ngTemplateOutletContext]="{ $implicit: node?.node }"
> >
</ng-container> </ng-container>
<ng-container <ng-container
*ngSwitchCase="NodeType.Buddy" *ngSwitchCase="NodeType.Buddy"
ngTemplateOutlet="buddyHeaderTemplate; context: {$implicit: node}" [ngTemplateOutlet]="buddyHeaderTemplate"
[ngTemplateOutletContext]="{ $implicit: node?.node }"
> >
</ng-container> </ng-container>
</ng-container> </ng-container>
@ -78,7 +80,9 @@
mat-icon-button mat-icon-button
aria-label="group-header-menu" aria-label="group-header-menu"
*ngIf="!checkable" *ngIf="!checkable"
(click)="onClickHeaderMenu($event, node)" (click)="
$event.stopPropagation(); onClickHeaderMenu($event, node)
"
> >
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>

View File

@ -1,22 +1,21 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core'; import { DebugElement } from '@angular/core';
import { ExpansionListComponent } from './expansion-list.component'; import { ExpansionComponent } from './expansion.component';
describe('ucap::ui-group::ExpansionListComponent', () => { describe('ucap::ui-group::ExpansionComponent', () => {
let component: ExpansionListComponent; let component: ExpansionComponent;
let fixture: ComponentFixture<ExpansionListComponent>; let fixture: ComponentFixture<ExpansionComponent>;
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ExpansionListComponent] declarations: [ExpansionComponent]
}).compileComponents(); }).compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(ExpansionListComponent); fixture = TestBed.createComponent(ExpansionComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
}); });

View File

@ -0,0 +1,16 @@
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
import { ExpansionComponent } from './expansion.component';
export default {
title: 'ExpansionComponent',
component: ExpansionComponent
};
export const Text = () => ({
component: ExpansionComponent,
props: {
text: 'Hello ExpansionComponent'
}
});

View File

@ -7,13 +7,13 @@ import {
EventEmitter, EventEmitter,
ViewChild, ViewChild,
ContentChild, ContentChild,
TemplateRef TemplateRef,
ChangeDetectionStrategy,
ChangeDetectorRef,
Directive
} from '@angular/core'; } from '@angular/core';
import { import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
VirtualScrollStrategy,
CdkVirtualScrollViewport
} from '@angular/cdk/scrolling';
import { FlatTreeControl } from '@angular/cdk/tree'; import { FlatTreeControl } from '@angular/cdk/tree';
import { MatTreeFlattener, MatTree } from '@angular/material/tree'; import { MatTreeFlattener, MatTree } from '@angular/material/tree';
@ -22,6 +22,9 @@ import { UserInfo, GroupDetailData } from '@ucap/protocol-sync';
import { VirtualScrollTreeFlatDataSource } from '@ucap/ng-ui'; import { VirtualScrollTreeFlatDataSource } from '@ucap/ng-ui';
import { UserInfoSS, UserInfoF, UserInfoDN } from '@ucap/protocol-query'; import { UserInfoSS, UserInfoF, UserInfoDN } from '@ucap/protocol-query';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
export enum NodeType { export enum NodeType {
None = 'None', None = 'None',
@ -44,19 +47,40 @@ export interface FlatNode {
node: GroupNode; node: GroupNode;
} }
@Component({ @Directive({
selector: 'ucap-group-expansion-list', selector: '[ucapGroupExpansionNode]'
templateUrl: './expansion-list.component.html',
styleUrls: ['./expansion-list.component.scss']
}) })
export class ExpansionListComponent implements OnInit, OnDestroy { export class ExpansionNodeDirective {}
@Directive({
selector: '[ucapGroupExpansionFavoriteHeader]'
})
export class ExpansionFavoriteHeaderDirective {}
@Directive({
selector: '[ucapGroupExpansionDefaultHeader]'
})
export class ExpansionDefaultHeaderDirective {}
@Directive({
selector: '[ucapGroupExpansionBuddyHeader]'
})
export class ExpansionBuddyHeaderDirective {}
@Component({
selector: 'ucap-group-expansion',
templateUrl: './expansion.component.html',
styleUrls: ['./expansion.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExpansionComponent implements OnInit, OnDestroy {
@Input() @Input()
virtualScrollStrategy: VirtualScrollStrategy; displayOrder: NodeType[] = [];
@Input() @Input()
set profile(userInfo: UserInfo) { set profile(userInfo: UserInfo) {
if (!userInfo) { if (!userInfo) {
this.profileNodes = []; this.nodeMap.set(NodeType.Profile, []);
} else { } else {
const node: GroupNode = { const node: GroupNode = {
nodeType: NodeType.Profile, nodeType: NodeType.Profile,
@ -64,7 +88,7 @@ export class ExpansionListComponent implements OnInit, OnDestroy {
children: [] children: []
}; };
this.profileNodes = [node]; this.nodeMap.set(NodeType.Profile, [node]);
} }
this.refreshNodes(); this.refreshNodes();
@ -73,7 +97,7 @@ export class ExpansionListComponent implements OnInit, OnDestroy {
@Input() @Input()
set favorites(userInfos: UserInfo[]) { set favorites(userInfos: UserInfo[]) {
if (!userInfos || 0 === userInfos.length) { if (!userInfos || 0 === userInfos.length) {
this.favoriteNodes = []; this.nodeMap.set(NodeType.Favorite, []);
} else { } else {
const node: GroupNode = { const node: GroupNode = {
nodeType: NodeType.Favorite, nodeType: NodeType.Favorite,
@ -93,7 +117,7 @@ export class ExpansionListComponent implements OnInit, OnDestroy {
}); });
}); });
this.favoriteNodes = [node]; this.nodeMap.set(NodeType.Favorite, [node]);
} }
this.refreshNodes(); this.refreshNodes();
@ -102,8 +126,12 @@ export class ExpansionListComponent implements OnInit, OnDestroy {
@Input() @Input()
set groupBuddies(list: { group: GroupDetailData; buddyList: UserInfo[] }[]) { set groupBuddies(list: { group: GroupDetailData; buddyList: UserInfo[] }[]) {
if (!list || 0 === list.length) { if (!list || 0 === list.length) {
this.buddyNodes = []; this.nodeMap.set(NodeType.Default, []);
this.nodeMap.set(NodeType.Buddy, []);
} else { } else {
this.nodeMap.set(NodeType.Default, []);
this.nodeMap.set(NodeType.Buddy, []);
for (const item of list) { for (const item of list) {
let nodeType = NodeType.Buddy; let nodeType = NodeType.Buddy;
if (0 === item.group.seq) { if (0 === item.group.seq) {
@ -136,7 +164,11 @@ export class ExpansionListComponent implements OnInit, OnDestroy {
}); });
}); });
this.buddyNodes.push(node); if (NodeType.Buddy === nodeType) {
this.nodeMap.get(NodeType.Buddy).push(node);
} else {
this.nodeMap.get(NodeType.Default).push(node);
}
} }
} }
@ -163,34 +195,44 @@ export class ExpansionListComponent implements OnInit, OnDestroy {
@ViewChild('cvsvList', { static: false }) @ViewChild('cvsvList', { static: false })
cvsvList: CdkVirtualScrollViewport; cvsvList: CdkVirtualScrollViewport;
@ContentChild('[ucapGroupExpansionList="node"]', { read: TemplateRef }) @ViewChild(PerfectScrollbarDirective, { static: false })
nodeTemplate: TemplateRef<any>; psDirectiveRef?: PerfectScrollbarDirective;
@ContentChild('[ucapGroupExpansionList="favoriteHeader"]', { @ContentChild(ExpansionNodeDirective, {
read: TemplateRef read: TemplateRef,
static: false
}) })
favoriteHeaderTemplate: TemplateRef<any>; nodeTemplate: TemplateRef<ExpansionNodeDirective>;
@ContentChild('[ucapGroupExpansionList="defaultHeader"]', { @ContentChild(ExpansionFavoriteHeaderDirective, {
read: TemplateRef read: TemplateRef,
static: false
}) })
defaultHeaderTemplate: TemplateRef<any>; favoriteHeaderTemplate: TemplateRef<ExpansionFavoriteHeaderDirective>;
@ContentChild('[ucapGroupExpansionList="buddyHeader"]', { read: TemplateRef }) @ContentChild(ExpansionDefaultHeaderDirective, {
buddyHeaderTemplate: TemplateRef<any>; read: TemplateRef,
static: false
})
defaultHeaderTemplate: TemplateRef<ExpansionDefaultHeaderDirective>;
@ContentChild(ExpansionBuddyHeaderDirective, {
read: TemplateRef,
static: false
})
buddyHeaderTemplate: TemplateRef<ExpansionBuddyHeaderDirective>;
rootNodeList: GroupNode[] = [];
treeControl: FlatTreeControl<FlatNode>; treeControl: FlatTreeControl<FlatNode>;
treeFlattener: MatTreeFlattener<GroupNode, FlatNode>; treeFlattener: MatTreeFlattener<GroupNode, FlatNode>;
dataSource: VirtualScrollTreeFlatDataSource<GroupNode, FlatNode>; dataSource: VirtualScrollTreeFlatDataSource<GroupNode, FlatNode>;
NodeType = NodeType; NodeType = NodeType;
private profileNodes: GroupNode[] = []; private nodeMap: Map<NodeType, GroupNode[]> = new Map();
private favoriteNodes: GroupNode[] = []; // tslint:disable-next-line: variable-name
private buddyNodes: GroupNode[] = []; private _ngOnDestroySubject: Subject<void>;
constructor() { constructor(private changeDetectorRef: ChangeDetectorRef) {
this.treeControl = new FlatTreeControl<FlatNode>( this.treeControl = new FlatTreeControl<FlatNode>(
(node) => node.level, (node) => node.level,
(node) => node.expandable (node) => node.expandable
@ -216,9 +258,24 @@ export class ExpansionListComponent implements OnInit, OnDestroy {
); );
} }
ngOnInit(): void {} ngOnInit(): void {
this._ngOnDestroySubject = new Subject();
ngOnDestroy(): void {} this.dataSource.cdkVirtualScrollViewport = this.cvsvList;
this.treeControl.expansionModel.changed
.pipe(takeUntil(this._ngOnDestroySubject))
.subscribe(() => {
this.cvsvList.checkViewportSize();
this.psDirectiveRef.update();
});
}
ngOnDestroy(): void {
if (!!this._ngOnDestroySubject) {
this._ngOnDestroySubject.next();
this._ngOnDestroySubject.complete();
}
}
onClickHeaderMenu(event: MouseEvent, node: FlatNode) {} onClickHeaderMenu(event: MouseEvent, node: FlatNode) {}
@ -276,11 +333,16 @@ export class ExpansionListComponent implements OnInit, OnDestroy {
NodeType.Profile !== node.node.nodeType && 0 === node.level; NodeType.Profile !== node.node.nodeType && 0 === node.level;
private refreshNodes() { private refreshNodes() {
this.rootNodeList = [ const rootNode: GroupNode[] = [];
...this.profileNodes,
...this.favoriteNodes, for (const nodeType of this.displayOrder) {
...this.buddyNodes const subNode = this.nodeMap.get(nodeType);
]; if (!!subNode && 0 < subNode.length) {
this.dataSource.data = this.rootNodeList; rootNode.push(...subNode);
}
}
this.dataSource.data = rootNode;
this.changeDetectorRef.detectChanges();
} }
} }

View File

@ -1,6 +1,8 @@
import { NgModule, ModuleWithProviders } from '@angular/core'; import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { ScrollingModule } from '@angular/cdk/scrolling'; import { ScrollingModule } from '@angular/cdk/scrolling';
import { MatRippleModule } from '@angular/material/core'; import { MatRippleModule } from '@angular/material/core';
@ -16,12 +18,23 @@ import { UiModule } from '@ucap/ng-ui';
import { ModuleConfig } from './config/module-config'; import { ModuleConfig } from './config/module-config';
import { _MODULE_CONFIG } from './config/token'; import { _MODULE_CONFIG } from './config/token';
import { ExpansionListComponent } from './components/expansion-list.component'; import {
ExpansionComponent,
ExpansionNodeDirective,
ExpansionFavoriteHeaderDirective,
ExpansionBuddyHeaderDirective,
ExpansionDefaultHeaderDirective
} from './components/expansion.component';
const COMPONENTS = [ExpansionListComponent]; const COMPONENTS = [ExpansionComponent];
const DIALOGS = []; const DIALOGS = [];
const PIPES = []; const PIPES = [];
const DIRECTIVES = []; const DIRECTIVES = [
ExpansionNodeDirective,
ExpansionFavoriteHeaderDirective,
ExpansionBuddyHeaderDirective,
ExpansionDefaultHeaderDirective
];
const SERVICES = []; const SERVICES = [];
@NgModule({ @NgModule({
@ -34,6 +47,8 @@ export class GroupUiRootModule {}
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, CommonModule,
FlexLayoutModule,
ScrollingModule, ScrollingModule,
MatButtonModule, MatButtonModule,

View File

@ -4,6 +4,6 @@
export * from './lib/config/module-config'; export * from './lib/config/module-config';
export * from './lib/components/expansion-list.component'; export * from './lib/components/expansion.component';
export * from './lib/group-ui.module'; export * from './lib/group-ui.module';

View File

@ -4,7 +4,9 @@
"lib": { "lib": {
"entryFile": "src/public-api.ts", "entryFile": "src/public-api.ts",
"umdModuleIds": { "umdModuleIds": {
"ngx-perfect-scrollbar": "ngx-perfect-scrollbar",
"@ucap/core": "@ucap/core", "@ucap/core": "@ucap/core",
"@ucap/ng-logger": "@ucap/ng-logger",
"@ucap/ng-ui": "@ucap/ng-ui" "@ucap/ng-ui": "@ucap/ng-ui"
} }
} }

View File

@ -1,8 +1,8 @@
{ {
"name": "@ucap/ng-ui-organization", "name": "@ucap/ng-ui-organization",
"version": "0.0.2", "version": "0.0.15",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/cdk": "^9.0.0", "@angular/cdk": "^9.0.0",

View File

@ -0,0 +1 @@
<div class="ucap-organization-profile-list-item-container"></div>

View File

@ -0,0 +1,26 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ProfileListItemComponent } from './profile-list-item.component';
describe('ucap::ui-organization::ProfileListItemComponent', () => {
let component: ProfileListItemComponent;
let fixture: ComponentFixture<ProfileListItemComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ProfileListItemComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProfileListItemComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
import { ProfileListItemComponent } from './profile-list-item.component';
export default {
title: 'ProfileListItemComponent',
component: ProfileListItemComponent
};
export const Text = () => ({
component: ProfileListItemComponent,
props: {
text: 'Hello ProfileListItemComponent'
}
});

View File

@ -0,0 +1,21 @@
import {
Component,
OnInit,
OnDestroy,
ChangeDetectionStrategy,
ChangeDetectorRef
} from '@angular/core';
@Component({
selector: 'ucap-organization-profile-list-item',
templateUrl: './profile-list-item.component.html',
styleUrls: ['./profile-list-item.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProfileListItemComponent implements OnInit, OnDestroy {
constructor(private changeDetectorRef: ChangeDetectorRef) {}
ngOnInit(): void {}
ngOnDestroy(): void {}
}

View File

@ -0,0 +1,62 @@
<div class="ucap-organization-tree-container" fxFlexFill>
<cdk-virtual-scroll-viewport #cvsvList perfectScrollbar fxFlexFill>
<ng-container
*cdkVirtualFor="let node of dataSource.expandedData$"
></ng-container>
<mat-tree #treeList [dataSource]="dataSource" [treeControl]="treeControl">
<mat-tree-node
*matTreeNodeDef="let node"
matTreeNodePadding
matTreeNodePaddingIndent="20"
class="tree-no-child"
>
<li
(click)="onClickNode(node)"
matRipple
[ngClass]="
currentDeptSeq === node?.data?.deptInfo?.seq ? 'current' : ''
"
>
<div class="tree-node-body">
{{ node?.data?.deptInfo | ucapOrganizationTranslate: 'name' }}
</div>
</li>
</mat-tree-node>
<mat-tree-node
*matTreeNodeDef="let node; when: hasChild"
matTreeNodePadding
matTreeNodePaddingIndent="20"
class="tree-has-child"
>
<li (click)="onClickNode(node)" matRipple>
<div
class="tree-node-body"
[ngClass]="
currentDeptSeq === node?.data?.deptInfo.seq ? 'current' : ''
"
>
<span class="horizontal-line"></span>
<button
mat-icon-button
color="accent"
matTreeNodeToggle
[attr.aria-label]="'toggle ' + node?.data?.filename"
>
<mat-icon
class="tree-node-expand-btn"
[@removeAdd]="treeControl.isExpanded(node) ? 'remove' : 'add'"
>
{{ treeControl.isExpanded(node) ? 'remove' : 'add' }}
</mat-icon>
</button>
<span class="dept-name">{{
node?.data?.deptInfo | ucapOrganizationTranslate: 'name'
}}</span>
</div>
</li>
</mat-tree-node>
</mat-tree>
</cdk-virtual-scroll-viewport>
</div>

View File

@ -0,0 +1,26 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { TreeComponent } from './tree.component';
describe('ucap::ui-organization::TreeComponent', () => {
let component: TreeComponent;
let fixture: ComponentFixture<TreeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TreeComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TreeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
import { TreeComponent } from './tree.component';
const TITLE = 'organization::TreeComponent';
export default {
title: `${TITLE}`,
component: TreeComponent
};
export const Blank = () => ({
props: {}
});

View File

@ -0,0 +1,186 @@
import {
Component,
OnInit,
OnDestroy,
Input,
ViewChild,
ChangeDetectionStrategy,
ChangeDetectorRef
} from '@angular/core';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { FlatTreeControl } from '@angular/cdk/tree';
import { MatTreeFlattener, MatTree } from '@angular/material/tree';
import { DeptInfo } from '@ucap/protocol-query';
import { VirtualScrollTreeFlatDataSource } from '@ucap/ng-ui';
import { LogService } from '@ucap/ng-logger';
import { LoginResponse } from '@ucap/protocol-authentication';
import { trigger, transition, style, animate } from '@angular/animations';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
export interface OrganizationNode {
deptInfo: DeptInfo;
children?: OrganizationNode[];
}
export interface FlatNode {
expandable: boolean;
level: number;
data: OrganizationNode;
}
@Component({
selector: 'ucap-organization-tree',
templateUrl: './tree.component.html',
styleUrls: ['./tree.component.scss'],
animations: [
trigger('removeAdd', [
transition('remove <=> add', [
style({
transform: `rotate(45deg)`,
opacity: 0
}),
animate('.2s 0s ease-out')
])
])
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TreeComponent implements OnInit, OnDestroy {
@Input()
loginRes: LoginResponse;
@Input()
set deptInfoList(data: { deptInfoList: DeptInfo[]; displayRoot?: boolean }) {
const deptInfoList = data.deptInfoList;
const displayRoot =
undefined === data.displayRoot ? true : data.displayRoot;
if (!deptInfoList || 0 === deptInfoList.length) {
return;
}
const nodeMap = new Map<number, OrganizationNode>();
let rootNodeList: OrganizationNode[] = [];
const remainChildNodeList: OrganizationNode[] = [];
deptInfoList.forEach((deptInfo) => {
const node: OrganizationNode = {
deptInfo,
children: []
};
if (nodeMap.has(deptInfo.seq)) {
this.logService.warn('duplicate seq', deptInfo.seq);
return;
}
nodeMap.set(deptInfo.seq, node);
if (0 === deptInfo.parentSeq) {
rootNodeList.push(node);
return;
}
if (nodeMap.has(deptInfo.parentSeq)) {
nodeMap.get(deptInfo.parentSeq).children.push(node);
} else {
remainChildNodeList.push(node);
}
});
if (
!displayRoot &&
0 < rootNodeList.length &&
0 === rootNodeList[0].deptInfo.parentSeq &&
!!rootNodeList[0].children &&
0 < rootNodeList[0].children.length
) {
rootNodeList = [...rootNodeList[0].children];
}
this._deptInfoList = deptInfoList;
remainChildNodeList.forEach((node) => {
if (nodeMap.has(node.deptInfo.parentSeq)) {
nodeMap.get(node.deptInfo.parentSeq).children.push(node);
}
});
this.dataSource.data = rootNodeList;
this.changeDetectorRef.detectChanges();
}
currentDeptSeq: number;
// tslint:disable-next-line: variable-name
_deptInfoList: DeptInfo[];
@ViewChild('treeList', { static: false })
treeList: MatTree<FlatNode>;
@ViewChild('cvsvList', { static: false })
cvsvList: CdkVirtualScrollViewport;
@ViewChild(PerfectScrollbarDirective, { static: false })
psDirectiveRef?: PerfectScrollbarDirective;
treeControl: FlatTreeControl<FlatNode>;
treeFlattener: MatTreeFlattener<OrganizationNode, FlatNode>;
dataSource: VirtualScrollTreeFlatDataSource<OrganizationNode, FlatNode>;
// tslint:disable-next-line: variable-name
private _ngOnDestroySubject: Subject<void>;
constructor(
private changeDetectorRef: ChangeDetectorRef,
private logService: LogService
) {
this.treeControl = new FlatTreeControl<FlatNode>(
(node) => node.level,
(node) => node.expandable
);
this.treeFlattener = new MatTreeFlattener<OrganizationNode, FlatNode>(
(node: OrganizationNode, level: number) => {
return {
expandable: !!node.children && node.children.length > 0,
level,
data: node
};
},
(node) => node.level,
(node) => node.expandable,
(node) => node.children
);
this.dataSource = new VirtualScrollTreeFlatDataSource<
OrganizationNode,
FlatNode
>(this.treeControl, this.treeFlattener);
}
ngOnInit(): void {
this._ngOnDestroySubject = new Subject();
this.dataSource.cdkVirtualScrollViewport = this.cvsvList;
this.treeControl.expansionModel.changed
.pipe(takeUntil(this._ngOnDestroySubject))
.subscribe(() => {
this.cvsvList.checkViewportSize();
this.psDirectiveRef.update();
});
}
ngOnDestroy(): void {
if (!!this._ngOnDestroySubject) {
this._ngOnDestroySubject.next();
this._ngOnDestroySubject.complete();
}
}
hasChild = (_: number, node: FlatNode) => node.expandable;
onClickNode(node: FlatNode) {}
}

View File

@ -1,16 +1,31 @@
import { NgModule, ModuleWithProviders } from '@angular/core'; import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { ScrollingModule } from '@angular/cdk/scrolling';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatIconModule } from '@angular/material/icon';
import { MatRippleModule } from '@angular/material/core';
import { MatTreeModule } from '@angular/material/tree';
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
import { UiModule } from '@ucap/ng-ui'; import { UiModule } from '@ucap/ng-ui';
import { ModuleConfig } from './config/module-config'; import { ModuleConfig } from './config/module-config';
import { _MODULE_CONFIG } from './config/token'; import { _MODULE_CONFIG } from './config/token';
import { ProfileListItemComponent } from './components/profile-list-item.component';
import { TreeComponent } from './components/tree.component';
import { TranslatePipe } from './pipes/translate.pipe'; import { TranslatePipe } from './pipes/translate.pipe';
import { TranslateService } from './services/translate.service'; import { TranslateService } from './services/translate.service';
const COMPONENTS = []; const COMPONENTS = [TreeComponent, ProfileListItemComponent];
const DIALOGS = []; const DIALOGS = [];
const PIPES = [TranslatePipe]; const PIPES = [TranslatePipe];
const DIRECTIVES = []; const DIRECTIVES = [];
@ -24,7 +39,21 @@ const SERVICES = [TranslateService];
export class OrganizationUiRootModule {} export class OrganizationUiRootModule {}
@NgModule({ @NgModule({
imports: [CommonModule, UiModule], imports: [
CommonModule,
FlexLayoutModule,
ScrollingModule,
MatButtonModule,
MatCheckboxModule,
MatIconModule,
MatRippleModule,
MatTreeModule,
PerfectScrollbarModule,
UiModule
],
exports: [...COMPONENTS, ...DIRECTIVES, ...PIPES], exports: [...COMPONENTS, ...DIRECTIVES, ...PIPES],
declarations: [...COMPONENTS, ...DIRECTIVES, ...PIPES], declarations: [...COMPONENTS, ...DIRECTIVES, ...PIPES],
entryComponents: [...DIALOGS] entryComponents: [...DIALOGS]

View File

@ -4,6 +4,9 @@
export * from './lib/config/module-config'; export * from './lib/config/module-config';
export * from './lib/components/profile-list-item.component';
export * from './lib/components/tree.component';
export * from './lib/pipes/translate.pipe'; export * from './lib/pipes/translate.pipe';
export * from './lib/services/translate.service'; export * from './lib/services/translate.service';

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-ui-skin-default", "name": "@ucap/ng-ui-skin-default",
"version": "0.0.1", "version": "0.0.1",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": {} "peerDependencies": {}
} }

View File

@ -1,8 +1,8 @@
{ {
"name": "@ucap/ng-ui", "name": "@ucap/ng-ui",
"version": "0.0.4", "version": "0.0.7",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/cdk": "^9.0.0", "@angular/cdk": "^9.0.0",

View File

@ -7,9 +7,9 @@
<button mat-fab class="fab-toggler bg-accent-dark" (click)="onToggleFab()"> <button mat-fab class="fab-toggler bg-accent-dark" (click)="onToggleFab()">
<mat-icon [@fabToggler]="fabTogglerState">add</mat-icon> <mat-icon [@fabToggler]="fabTogglerState">add</mat-icon>
</button> </button>
<div [@speedDialStagger]="buttons.length"> <div [@speedDialStagger]="_buttons.length">
<button <button
*ngFor="let btn of buttons" *ngFor="let btn of _buttons"
mat-mini-fab mat-mini-fab
[matTooltip]="btn.tooltip" [matTooltip]="btn.tooltip"
matTooltipPosition="before" matTooltipPosition="before"

View File

@ -38,7 +38,7 @@ export class FloatActionButtonComponent implements OnInit {
hideItems() { hideItems() {
this.fabTogglerState = 'inactive'; this.fabTogglerState = 'inactive';
this.buttons = []; this._buttons = [];
} }
getTooltip(btn: FloatActionButton) { getTooltip(btn: FloatActionButton) {

View File

@ -43,11 +43,11 @@ export class SplitButtonComponent implements OnInit, OnDestroy {
ngOnInit() { ngOnInit() {
this.menuCloseSubscription = this.menu.close.subscribe(() => { this.menuCloseSubscription = this.menu.close.subscribe(() => {
this.matMenuTrigger._handleClick = e => {}; this.matMenuTrigger._handleClick = (e) => {};
this.splitOpened = false; this.splitOpened = false;
}); });
this._handleClick = this.matMenuTrigger._handleClick; this._handleClick = this.matMenuTrigger._handleClick;
this.matMenuTrigger._handleClick = e => {}; this.matMenuTrigger._handleClick = (e) => {};
} }
ngOnDestroy(): void { ngOnDestroy(): void {

View File

@ -1,11 +1,5 @@
import { import { BehaviorSubject, merge, Observable, Subject } from 'rxjs';
BehaviorSubject, import { map, share, takeUntil } from 'rxjs/operators';
merge,
Observable,
Subject,
Subscription
} from 'rxjs';
import { map, share } from 'rxjs/operators';
import { CollectionViewer, DataSource } from '@angular/cdk/collections'; import { CollectionViewer, DataSource } from '@angular/cdk/collections';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
@ -21,10 +15,9 @@ export class VirtualScrollTreeFlatDataSource<T, F> extends DataSource<F> {
private _flattenedDataSubject = new BehaviorSubject<F[]>([]); private _flattenedDataSubject = new BehaviorSubject<F[]>([]);
// tslint:disable-next-line: variable-name // tslint:disable-next-line: variable-name
private _connectSubject: Subject<F[]>; private _connectSubject: Subject<F[]>;
// tslint:disable-next-line: variable-name // tslint:disable-next-line: variable-name
private _dataChangeSubscription: Subscription; private _destroySubject = new Subject<boolean>();
// tslint:disable-next-line: variable-name
private _rangeChangeSubscription: Subscription;
// tslint:disable-next-line: variable-name // tslint:disable-next-line: variable-name
private _rangeSubject: BehaviorSubject<{ private _rangeSubject: BehaviorSubject<{
@ -41,13 +34,17 @@ export class VirtualScrollTreeFlatDataSource<T, F> extends DataSource<F> {
return; return;
} }
this._cdkVirtualScrollViewport = cdkVirtualScrollViewport; this._cdkVirtualScrollViewport = cdkVirtualScrollViewport;
this._rangeSubject = new BehaviorSubject<{ start: number; end: number }>({ this._rangeSubject = new BehaviorSubject<{
start: number;
end: number;
}>({
start: 0, start: 0,
end: 1 end: 1
}); });
this._rangeChangeSubscription = cdkVirtualScrollViewport.renderedRangeStream.subscribe( cdkVirtualScrollViewport.renderedRangeStream
(range) => { .pipe(takeUntil(this._destroySubject))
.subscribe((range) => {
this._rangeSubject.next({ this._rangeSubject.next({
start: range.start, start: range.start,
end: range.end end: range.end
@ -60,8 +57,7 @@ export class VirtualScrollTreeFlatDataSource<T, F> extends DataSource<F> {
) )
); );
} }
} });
);
} }
// tslint:disable-next-line: variable-name // tslint:disable-next-line: variable-name
@ -90,14 +86,17 @@ export class VirtualScrollTreeFlatDataSource<T, F> extends DataSource<F> {
} }
connect(collectionViewer: CollectionViewer): Observable<F[]> { connect(collectionViewer: CollectionViewer): Observable<F[]> {
this._destroySubject = new Subject<boolean>();
this._connectSubject = new Subject<F[]>(); this._connectSubject = new Subject<F[]>();
this._dataChangeSubscription = merge( merge(
collectionViewer.viewChange, collectionViewer.viewChange,
this._treeControl.expansionModel.changed, this._treeControl.expansionModel.changed,
this._flattenedDataSubject this._flattenedDataSubject
) )
.pipe( .pipe(
takeUntil(this._destroySubject),
map(() => { map(() => {
this.expandedDataSubject.next( this.expandedDataSubject.next(
this._treeFlattener.expandFlattenedNodes( this._treeFlattener.expandFlattenedNodes(
@ -130,12 +129,8 @@ export class VirtualScrollTreeFlatDataSource<T, F> extends DataSource<F> {
this._connectSubject.unsubscribe(); this._connectSubject.unsubscribe();
} }
if (!!this._dataChangeSubscription) { if (!!this._destroySubject) {
this._dataChangeSubscription.unsubscribe(); this._destroySubject.complete();
}
if (!!this._rangeChangeSubscription) {
this._rangeChangeSubscription.unsubscribe();
} }
} }
} }

View File

@ -11,7 +11,7 @@ import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
}) })
export class CdkVirtualScrollViewportPatchDirective export class CdkVirtualScrollViewportPatchDirective
implements OnInit, OnDestroy { implements OnInit, OnDestroy {
protected readonly destroySubject = new Subject(); protected destroySubject: Subject<boolean>;
constructor( constructor(
@Self() @Self()
@ -20,15 +20,19 @@ export class CdkVirtualScrollViewportPatchDirective
) {} ) {}
ngOnInit() { ngOnInit() {
this.destroySubject = new Subject();
fromEvent(document.defaultView, 'resize') fromEvent(document.defaultView, 'resize')
.pipe(debounceTime(10), takeUntil(this.destroySubject)) .pipe(takeUntil(this.destroySubject), debounceTime(10))
.subscribe(() => { .subscribe(() => {
this.viewportComponent.checkViewportSize(); this.viewportComponent.checkViewportSize();
}); });
} }
ngOnDestroy() { ngOnDestroy() {
this.destroySubject.next(); if (!!this.destroySubject) {
this.destroySubject.complete(); this.destroySubject.next();
this.destroySubject.complete();
}
} }
} }

View File

@ -265,4 +265,41 @@ export class DateService {
return m.format('MM.DD'); return m.format('MM.DD');
} }
} }
/**
* Checking today
* @returns boolean true is today.
*/
public isToday(date: any, options?: DateOptions): boolean {
if (!date || 0 === date.length) {
return false;
}
let d = moment.tz(date, 'Asia/Seoul').utc();
d = d.tz(this.currentTimezone);
if (!!options) {
if (!!options.manipulate) {
if (!!options.manipulate.amount && !!options.manipulate.unit) {
d = d.add(options.manipulate.amount, options.manipulate.unit);
}
if (!!options.manipulate.startOf) {
d = d.startOf(options.manipulate.startOf);
}
if (!!options.manipulate.endOf) {
d = d.startOf(options.manipulate.endOf);
}
}
}
const today = moment();
if (d.isSame(today, 'day')) {
return true;
} else {
return false;
}
}
} }

View File

@ -0,0 +1,52 @@
import { TemplateRef, Injectable } from '@angular/core';
import { ComponentType } from '@angular/cdk/portal';
import {
MatDialog,
MatDialogConfig,
MatDialogRef
} from '@angular/material/dialog';
import { of } from 'rxjs';
import { take, map, catchError } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class DialogService {
constructor(private matDialog: MatDialog) {}
public open<T, D = any, R = any>(
componentOrTemplateRef: ComponentType<T> | TemplateRef<T>,
config?: MatDialogConfig<D>
): Promise<R> {
return new Promise<R>((resolve, reject) => {
config = { ...config, autoFocus: false };
const dialogRef = this.matDialog.open<T, D, R>(
componentOrTemplateRef,
config
);
dialogRef
.afterClosed()
.pipe(
take(1),
map(result => {
return resolve(result);
}),
catchError(err => {
return of(reject(err));
})
)
.subscribe();
});
}
getDialogById(id: string): MatDialogRef<any, any> {
return this.matDialog.getDialogById(id);
}
closeAll() {
this.matDialog.closeAll();
}
}

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-web-socket", "name": "@ucap/ng-web-socket",
"version": "0.0.2", "version": "0.0.2",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",

View File

@ -2,7 +2,7 @@
"name": "@ucap/ng-web-storage", "name": "@ucap/ng-web-storage",
"version": "0.0.3", "version": "0.0.3",
"publishConfig": { "publishConfig": {
"registry": "http://10.81.13.221:8081/nexus/repository/npm-ucap/" "registry": "http://10.81.13.229:8081/repository/npm-ucap/"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "^9.0.2", "@angular/common": "^9.0.2",