This commit is contained in:
leejh 2019-11-06 14:06:39 +09:00
commit bca6a54a24
93 changed files with 1143 additions and 1112 deletions

View File

@ -9,7 +9,6 @@ import {
JsonAnalization,
APIFormDataEncoder
} from '@ucap-webmessenger/api';
import { JsonObject } from 'type-fest';
import { FileUploadItem } from '../models/file-upload-item';
export interface FileTalkSaveRequest extends APIRequest {
@ -73,7 +72,7 @@ export const decodeFileTalkSave: APIDecoder<FileTalkSaveResponse> = (
res: any
) => {
try {
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
const json = JsonAnalization.receiveAnalization(res);
return {
statusCode: json.StatusCode,
roomSeq: json.RoomID,

View File

@ -8,7 +8,6 @@ import {
JsonAnalization,
StatusCode
} from '@ucap-webmessenger/api';
import { JsonObject } from 'type-fest';
export interface FileTalkShareRequest extends APIRequest {
userSeq: string;
@ -52,7 +51,7 @@ export const decodeFileTalkShare: APIDecoder<FileTalkShareResponse> = (
res: any
) => {
try {
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
const json = JsonAnalization.receiveAnalization(res);
return {
statusCode: json.StatusCode,
roomSeq: json.RoomID,

View File

@ -8,7 +8,6 @@ import {
JsonAnalization,
StatusCode
} from '@ucap-webmessenger/api';
import { JsonObject } from 'type-fest';
export interface MassTalkDownloadRequest extends APIRequest {
userSeq: number;
@ -40,7 +39,7 @@ export const decodeMassTalkDownload: APIDecoder<MassTalkDownloadResponse> = (
res: any
) => {
try {
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
const json = JsonAnalization.receiveAnalization(res);
return {
statusCode: json.StatusCode,
errorMessage: json.ErrorMessage,

View File

@ -8,7 +8,6 @@ import {
StatusCode,
JsonAnalization
} from '@ucap-webmessenger/api';
import { JsonObject } from 'type-fest';
export interface MassTalkSaveRequest extends APIRequest {
userSeq: number;
@ -44,7 +43,7 @@ export const decodeMassTalkSave: APIDecoder<MassTalkSaveResponse> = (
res: any
) => {
try {
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
const json = JsonAnalization.receiveAnalization(res);
return {
statusCode: json.StatusCode,
errorMessage: json.ErrorMessage,

View File

@ -8,7 +8,6 @@ import {
JsonAnalization,
StatusCode
} from '@ucap-webmessenger/api';
import { JsonObject } from 'type-fest';
export interface TransMassTalkSaveRequest extends APIRequest {
userSeq: string;
@ -50,7 +49,7 @@ export const decodeTransMassTalkSave: APIDecoder<TransMassTalkSaveResponse> = (
res: any
) => {
try {
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
const json = JsonAnalization.receiveAnalization(res);
return {
statusCode: json.StatusCode,
translationSeq: json.EventTransSEQ,

View File

@ -8,7 +8,6 @@ import {
JsonAnalization,
StatusCode
} from '@ucap-webmessenger/api';
import { JsonObject } from 'type-fest';
export interface TranslationSaveRequest extends APIRequest {
userSeq: string;
@ -51,7 +50,7 @@ export const decodeTranslationSave: APIDecoder<TranslationSaveResponse> = (
res: any
) => {
try {
const json: JsonObject | Error = JsonAnalization.receiveAnalization(res);
const json = JsonAnalization.receiveAnalization(res);
return {
statusCode: json.StatusCode,
translationSeq: json.EventTransSEQ,

View File

@ -1,11 +1,9 @@
import { JsonObject } from 'type-fest';
export class JsonAnalization {
/**
* Raw string Analization for JSON string.
* @description Editing with string.util.ts
*/
public static receiveAnalization(jsonStr: string): JsonObject {
public static receiveAnalization(jsonStr: string): any {
const startJson = jsonStr.indexOf('{');
const endJson = jsonStr.lastIndexOf('}');

View File

@ -0,0 +1 @@
<ucap-file-viewer></ucap-file-viewer>

View File

@ -3,20 +3,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ImageViewerDialogComponent } from './image-viewer.dialog.component';
import { FileViewerDialogComponent } from './file-viewer.dialog.component';
describe('ImageViewerDialogComponent', () => {
let component: ImageViewerDialogComponent;
let fixture: ComponentFixture<ImageViewerDialogComponent>;
describe('FileViewerDialogComponent', () => {
let component: FileViewerDialogComponent;
let fixture: ComponentFixture<FileViewerDialogComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ImageViewerDialogComponent]
declarations: [FileViewerDialogComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ImageViewerDialogComponent);
fixture = TestBed.createComponent(FileViewerDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -0,0 +1,34 @@
import {
Component,
OnInit,
OnDestroy,
Inject,
EventEmitter
} from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { NGXLogger } from 'ngx-logger';
export interface FileViewerDialogData {}
export interface FileViewerDialogResult {}
@Component({
selector: 'app-layout-common-file-viewer',
templateUrl: './file-viewer.dialog.component.html',
styleUrls: ['./file-viewer.dialog.component.scss']
})
export class FileViewerDialogComponent implements OnInit, OnDestroy {
constructor(
public dialogRef: MatDialogRef<
FileViewerDialogData,
FileViewerDialogResult
>,
@Inject(MAT_DIALOG_DATA) public data: FileViewerDialogData,
private logger: NGXLogger
) {}
ngOnInit() {}
ngOnDestroy(): void {}
}

View File

@ -1,34 +0,0 @@
import {
Component,
OnInit,
OnDestroy,
Inject,
EventEmitter
} from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { NGXLogger } from 'ngx-logger';
export interface ImageViewerDialogData {}
export interface ImageViewerDialogResult {}
@Component({
selector: 'app-layout-common-image-viewer',
templateUrl: './image-viewer.dialog.component.html',
styleUrls: ['./image-viewer.dialog.component.scss']
})
export class ImageViewerDialogComponent implements OnInit, OnDestroy {
constructor(
public dialogRef: MatDialogRef<
ImageViewerDialogData,
ImageViewerDialogResult
>,
@Inject(MAT_DIALOG_DATA) public data: ImageViewerDialogData,
private logger: NGXLogger
) {}
ngOnInit() {}
ngOnDestroy(): void {}
}

View File

@ -1,3 +1,3 @@
import { ImageViewerDialogComponent } from './image-viewer.dialog.component';
import { FileViewerDialogComponent } from './file-viewer.dialog.component';
export const DIALOGS = [ImageViewerDialogComponent];
export const DIALOGS = [FileViewerDialogComponent];

View File

@ -28,7 +28,8 @@ import {
isRecalled,
isCopyable,
isRecallable,
InfoResponse
InfoResponse,
EventJson
} from '@ucap-webmessenger/protocol-event';
import * as AppStore from '@app/store';
@ -63,10 +64,10 @@ import {
CreateChatDialogResult
} from '../dialogs/chat/create-chat.dialog.component';
import {
ImageViewerDialogComponent,
ImageViewerDialogData,
ImageViewerDialogResult
} from '@app/layouts/common/dialogs/image-viewer.dialog.component';
FileViewerDialogComponent,
FileViewerDialogData,
FileViewerDialogResult
} from '@app/layouts/common/dialogs/file-viewer.dialog.component';
import { CONST } from '@ucap-webmessenger/core';
import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar';
import { StatusCode } from '@ucap-webmessenger/api';
@ -103,7 +104,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
loginRes: LoginResponse;
loginResSubscription: Subscription;
eventList$: Observable<Info[]>;
eventList$: Observable<Info<EventJson>[]>;
baseEventSeq = 0;
roomInfo: RoomInfo;
roomInfoSubscription: Subscription;
@ -355,10 +356,10 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
async onImageViewer(value: FileInfo) {
this.logger.debug('imageViewer', value);
const result = await this.dialogService.open<
ImageViewerDialogComponent,
ImageViewerDialogData,
ImageViewerDialogResult
>(ImageViewerDialogComponent, {
FileViewerDialogComponent,
FileViewerDialogData,
FileViewerDialogResult
>(FileViewerDialogComponent, {
position: {
top: '30px'
},
@ -367,6 +368,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
height: 'calc(100% - 30px)',
width: '100%',
hasBackdrop: false,
panelClass: 'app-dialog-full',
data: {}
});
}
@ -453,7 +455,10 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
);
}
onContextMenuMessage(params: { event: MouseEvent; message: Info }) {
onContextMenuMessage(params: {
event: MouseEvent;
message: Info<EventJson>;
}) {
params.event.preventDefault();
params.event.stopPropagation();
@ -467,7 +472,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
this.messageContextMenuTrigger.openMenu();
}
async onClickMessageContextMenu(menuType: string, message: Info) {
async onClickMessageContextMenu(menuType: string, message: Info<EventJson>) {
switch (menuType) {
case 'COPY':
{
@ -475,7 +480,9 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
case EventType.Character:
{
if (
this.clipboardService.copyFromContent(message.sentMessage)
this.clipboardService.copyFromContent(
(message as Info<string>).sentMessage
)
) {
this.snackBarService.open('클립보드에 복사되었습니다.', '', {
duration: 3000,

View File

@ -13,7 +13,7 @@ import {
} from '@ucap-webmessenger/protocol-status';
import { Router } from '@angular/router';
import { Company } from '@ucap-webmessenger/api-external';
import { EventType, Info } from '@ucap-webmessenger/protocol-event';
import { EventType, Info, EventJson } from '@ucap-webmessenger/protocol-event';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { StatusCode as ApiStatusCode } from '@ucap-webmessenger/api';
import { StatusCode } from '@ucap-webmessenger/core';
@ -302,7 +302,7 @@ const companyList: Company[] = [
}
];
const eventInfo: Info[] = [
const eventInfo: Info<EventJson>[] = [
{
seq: 6,
type: EventType.Character,

View File

@ -1,5 +1,5 @@
import { createAction, props } from '@ngrx/store';
import { Info } from '@ucap-webmessenger/protocol-event';
import { Info, EventJson } from '@ucap-webmessenger/protocol-event';
import {
MassTalkDownloadRequest,
MassTalkDownloadResponse
@ -18,7 +18,7 @@ export const newEventMessage = createAction(
'[Messenger::Chat] newEventMessage',
props<{
roomSeq: string;
info: Info;
info: Info<EventJson>;
}>()
);

View File

@ -13,7 +13,8 @@ import {
DelRequest,
DelResponse,
CancelRequest,
CancelResponse
CancelResponse,
EventJson
} from '@ucap-webmessenger/protocol-event';
export const info = createAction(
@ -24,7 +25,7 @@ export const info = createAction(
export const infoSuccess = createAction(
'[Messenger::Event] Info Success',
props<{
infoList: Info[];
infoList: Info<EventJson>[];
res: InfoResponse;
}>()
);
@ -32,7 +33,7 @@ export const infoSuccess = createAction(
export const infoMoreSuccess = createAction(
'[Messenger::Event] Info More Success',
props<{
infoList: Info[];
infoList: Info<EventJson>[];
res: InfoResponse;
}>()
);
@ -51,7 +52,7 @@ export const newInfo = createAction(
'[Messenger::Event] New Info',
props<{
roomSeq: string;
info: Info;
info: Info<EventJson>;
SVC_TYPE?: number;
SSVC_TYPE?: number;
}>()
@ -60,7 +61,7 @@ export const newInfo = createAction(
export const appendInfoList = createAction(
'[Messenger::Event] Append InfoList',
props<{
info: Info;
info: Info<EventJson>;
}>()
);
@ -134,7 +135,7 @@ export const read = createAction(
export const readSuccess = createAction(
'[Messenger::Event] read Success',
props<{
infoList: Info[];
infoList: Info<EventJson>[];
res: InfoResponse;
}>()
);

View File

@ -36,7 +36,8 @@ import {
EventType,
ReadNotification,
SSVC_TYPE_EVENT_SEND_RES,
SSVC_TYPE_EVENT_SEND_NOTI
SSVC_TYPE_EVENT_SEND_NOTI,
EventJson
} from '@ucap-webmessenger/protocol-event';
import * as ChatStore from '@app/store/messenger/chat';
@ -102,7 +103,7 @@ export class Effects {
info$ = createEffect(
() => {
let infoList: Info[];
let infoList: Info<EventJson>[];
return this.actions$.pipe(
ofType(info),
@ -170,7 +171,9 @@ export class Effects {
this.store.pipe(
select(
(state: any) =>
state.messenger.event.infoList.entities as Dictionary<Info>
state.messenger.event.infoList.entities as Dictionary<
Info<EventJson>
>
)
)
),
@ -179,7 +182,7 @@ export class Effects {
const delEventSeq: number[] = [];
// tslint:disable-next-line: forin
for (const key in eventList) {
const event: Info = eventList[key];
const event: Info<EventJson> = eventList[key];
if (
new Date().getTime() - new Date(event.sendDate).getTime() >=
roomInfo.timeRoomInterval * 1000
@ -276,19 +279,11 @@ export class Effects {
ofType(sendSuccess),
tap(action => {
const res = action.res;
const appendInfo: Info = {
seq: res.seq,
type: res.eventType,
senderSeq: action.senderSeq,
sendDate: res.sendDate,
sentMessage: res.message,
receiverCount: res.receiverCount
};
this.store.dispatch(
newInfo({
roomSeq: res.roomSeq,
info: appendInfo,
info: res.info,
SVC_TYPE: res.SVC_TYPE,
SSVC_TYPE: res.SSVC_TYPE
})
@ -305,19 +300,10 @@ export class Effects {
ofType(sendNotification),
map(action => action.noti),
tap(noti => {
const appendInfo: Info = {
seq: noti.seq,
type: noti.eventType,
senderSeq: noti.SENDER_SEQ,
sendDate: noti.sendDate,
sentMessage: noti.message,
receiverCount: noti.receiverCount
};
this.store.dispatch(
newInfo({
roomSeq: noti.roomSeq,
info: appendInfo,
info: noti.info,
SVC_TYPE: noti.SVC_TYPE,
SSVC_TYPE: noti.SSVC_TYPE
})

View File

@ -10,7 +10,7 @@ import {
infoMoreSuccess
} from './actions';
import * as AuthenticationStore from '@app/store/account/authentication';
import { Info, EventType } from '@ucap-webmessenger/protocol-event';
import { Info, EventType, EventJson } from '@ucap-webmessenger/protocol-event';
import { CONST } from '@ucap-webmessenger/core';
export const reducer = createReducer(
@ -63,7 +63,7 @@ export const reducer = createReducer(
on(appendInfoList, (state, action) => {
const eventinfo = action.info;
const statusEventInfo: Info = {
const statusEventInfo: Info<EventJson> = {
...state.infoList.entities[eventinfo.seq],
type: eventinfo.type,
senderSeq: eventinfo.senderSeq,
@ -81,7 +81,7 @@ export const reducer = createReducer(
on(recallInfoList, (state, action) => {
const eventSeq = action.eventSeq;
const statusEventInfo: Info = {
const statusEventInfo: Info<EventJson> = {
...state.infoList.entities[eventSeq],
type: EventType.RecalledMessage,
sentMessage: '회수된 메시지'

View File

@ -1,8 +1,12 @@
import { Selector, createSelector } from '@ngrx/store';
import { InfoResponse, Info } from '@ucap-webmessenger/protocol-event';
import {
InfoResponse,
Info,
EventJson
} from '@ucap-webmessenger/protocol-event';
import { EntityState, createEntityAdapter } from '@ngrx/entity';
export interface InfoListState extends EntityState<Info> {}
export interface InfoListState extends EntityState<Info<EventJson>> {}
export interface State {
infoListProcessing: boolean;
@ -11,7 +15,7 @@ export interface State {
remainInfo: boolean;
}
export const adapterInfoList = createEntityAdapter<Info>({
export const adapterInfoList = createEntityAdapter<Info<EventJson>>({
selectId: info => info.seq,
sortComparer: (a, b) => {
return a.seq - b.seq;

View File

@ -13,7 +13,7 @@ import {
UserInfo as RoomUserInfo,
InfoRequest
} from '@ucap-webmessenger/protocol-room';
import { Info } from '@ucap-webmessenger/protocol-event';
import { Info, EventJson } from '@ucap-webmessenger/protocol-event';
import {
AddResponse as GroupAddResponse,
UpdateRequest as GroupUpdateRequest,
@ -88,7 +88,7 @@ export const updateRoomForNewEventMessage = createAction(
'[Messenger::Sync] updateRoomForNewEventMessage',
props<{
roomSeq: string;
info: Info;
info: Info<EventJson>;
}>()
);

View File

@ -111,8 +111,8 @@ $lg-red: (
.text-accent-color {
color: mat-color($accent);
}
.text-warn-color{
color:mat-color($warn);
.text-warn-color {
color: mat-color($warn);
}
.border-primary-color {
border: 1px solid mat-color($primary);
@ -144,4 +144,12 @@ $lg-red: (
background-color: mat-color($primary);
}
}
.app-dialog-full .mat-dialog-container {
overflow: hidden;
padding: 0px;
background-color: rgba($color: #000000, $alpha: 0.3);
box-shadow: none;
border-radius: 0px;
}
}

View File

@ -1,37 +0,0 @@
// Media step breakpoint mixin based on Angular Material lib
$breakpoints: (
xs: 'screen and (max-width: 599px)',
sm: 'screen and (min-width: 600px) and (max-width: 959px)',
md: 'screen and (min-width: 960px) and (max-width: 1279px)',
lg: 'screen and (min-width: 1280px) and (max-width: 1919px)',
xl: 'screen and (min-width: 1920px) and (max-width: 5000px)',
lt-sm: 'screen and (max-width: 599px)',
lt-md: 'screen and (max-width: 959px)',
lt-lg: 'screen and (max-width: 1279px)',
lt-xl: 'screen and (max-width: 1919px)',
gt-xs: 'screen and (min-width: 600px)',
gt-sm: 'screen and (min-width: 960px)',
gt-md: 'screen and (min-width: 1280px)',
gt-lg: 'screen and (min-width: 1920px)'
) !default;
// Re-map the breakpoints for the helper classes
$helper-breakpoints: (
xs: null,
sm: 'gt-xs',
md: 'gt-sm',
lg: 'gt-md',
xl: 'gt-lg'
);
@mixin media-breakpoint($breakpointName) {
$mediaQuery: map-get($breakpoints, $breakpointName);
@if ($mediaQuery == null) {
@content;
} @else {
@media #{$mediaQuery} {
@content;
}
}
}

View File

@ -1,15 +0,0 @@
button,
input[type='email'],
input[type='tel'],
input[type='text'],
input[type='password'],
input[type='image'],
input[type='submit'],
input[type='button'],
input[type='search'],
textarea {
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
outline: none;
}

View File

@ -1,70 +0,0 @@
// -----------------------------------------------------------------------------------------------------
// @ Body scroll lock
// -----------------------------------------------------------------------------------------------------
html,
body {
display: flex;
flex: 1 0 auto;
width: 100%;
height: 100%;
max-height: 100%;
min-height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
// -----------------------------------------------------------------------------------------------------
// @ Boxed body
// -----------------------------------------------------------------------------------------------------
body {
// Boxed
&.boxed {
max-width: 1200px;
margin: 0 auto;
@include mat-elevation(8);
}
}
/*----------------------------------------------------------------*/
/* @ Text rendering & box sizing
/*----------------------------------------------------------------*/
* {
text-rendering: optimizeLegibility;
-o-text-rendering: optimizeLegibility;
-ms-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
-webkit-text-rendering: optimizeLegibility;
-webkit-tap-highlight-color: transparent;
box-sizing: border-box;
&:before,
&:after {
box-sizing: border-box;
}
// Remove focus outline
&:focus {
outline: none;
}
}
// -----------------------------------------------------------------------------------------------------
// @ Responsive images
// -----------------------------------------------------------------------------------------------------
img {
max-width: 100%;
height: auto;
vertical-align: top;
border: none;
}
// -----------------------------------------------------------------------------------------------------
// @ Input
// -----------------------------------------------------------------------------------------------------
input {
border: none;
padding: 0 16px;
}

View File

@ -1,236 +0,0 @@
// -----------------------------------------------------------------------------------------------------
// @ Position helpers
// -----------------------------------------------------------------------------------------------------
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
@include media-breakpoint($materialBreakpoint) {
$infix: if($materialBreakpoint == null, '', '-#{$breakpoint}');
.position#{$infix}-relative {
position: relative;
}
.position#{$infix}-absolute {
position: absolute;
}
.position#{$infix}-static {
position: static;
}
}
}
// -----------------------------------------------------------------------------------------------------
// @ Absolute position alignment helpers
// -----------------------------------------------------------------------------------------------------
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
@include media-breakpoint($materialBreakpoint) {
$infix: if($materialBreakpoint == null, '', '-#{$breakpoint}');
.align#{$infix}-top {
top: 0;
}
.align#{$infix}-right {
right: 0;
}
.align#{$infix}-bottom {
bottom: 0;
}
.align#{$infix}-left {
left: 0;
}
}
}
// -----------------------------------------------------------------------------------------------------
// @ Size helpers
// -----------------------------------------------------------------------------------------------------
@each $prop, $abbrev in (height: h, width: w) {
@for $index from 0 through 180 {
$size: $index * 4;
$length: #{$size}px;
.#{$abbrev}-#{$size} {
#{$prop}: $length !important;
min-#{$prop}: $length !important;
max-#{$prop}: $length !important;
}
}
// Percentage
@for $i from 0 through 20 {
$i-p: 5 * $i;
$size-p: 5% * $i;
.#{$abbrev}-#{$i-p}-p {
#{$prop}: $size-p !important;
}
}
}
// -----------------------------------------------------------------------------------------------------
// @ Spacing helpers
// -----------------------------------------------------------------------------------------------------
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
@include media-breakpoint($materialBreakpoint) {
$infix: if($materialBreakpoint == null, '', '-#{$breakpoint}');
@each $prop, $abbrev in (margin: m, padding: p) {
@for $index from 0 through 64 {
$size: $index * 4;
$length: #{$size}px;
.#{$abbrev}#{$infix}-#{$size} {
#{$prop}: $length !important;
}
}
@for $index from 0 through 64 {
$size: $index * 4;
$length: #{$size}px;
.#{$abbrev}x#{$infix}-#{$size} {
#{$prop}-right: $length !important;
#{$prop}-left: $length !important;
}
.#{$abbrev}y#{$infix}-#{$size} {
#{$prop}-top: $length !important;
#{$prop}-bottom: $length !important;
}
}
@for $index from 0 through 64 {
$size: $index * 4;
$length: #{$size}px;
.#{$abbrev}t#{$infix}-#{$size} {
#{$prop}-top: $length !important;
}
.#{$abbrev}r#{$infix}-#{$size} {
#{$prop}-right: $length !important;
}
.#{$abbrev}b#{$infix}-#{$size} {
#{$prop}-bottom: $length !important;
}
.#{$abbrev}l#{$infix}-#{$size} {
#{$prop}-left: $length !important;
}
}
@if ($abbrev == m) {
// Some special margin utils for flex alignments
.m#{$infix}-auto {
margin: auto !important;
}
.mt#{$infix}-auto {
margin-top: auto !important;
}
.mr#{$infix}-auto {
margin-right: auto !important;
}
.mb#{$infix}-auto {
margin-bottom: auto !important;
}
.ml#{$infix}-auto {
margin-left: auto !important;
}
.mx#{$infix}-auto {
margin-right: auto !important;
margin-left: auto !important;
}
.my#{$infix}-auto {
margin-top: auto !important;
margin-bottom: auto !important;
}
}
}
}
}
// -----------------------------------------------------------------------------------------------------
// @ Border helpers
// -----------------------------------------------------------------------------------------------------
$border-style: 1px solid rgba(0, 0, 0, 0.12);
.border,
.b {
border: $border-style;
}
.border-top,
.bt {
border-top: $border-style;
}
.border-right,
.br {
border-right: $border-style;
}
.border-bottom,
.bb {
border-bottom: $border-style;
}
.border-left,
.bl {
border-left: $border-style;
}
.border-horizontal,
.bx {
border-left: $border-style;
border-right: $border-style;
}
.border-vertical,
.by {
border-top: $border-style;
border-bottom: $border-style;
}
// -----------------------------------------------------------------------------------------------------
// @ Border radius helpers
// -----------------------------------------------------------------------------------------------------
.border-radius-100 {
border-radius: 100%;
}
.border-radius-2 {
border-radius: 2px;
}
.border-radius-4 {
border-radius: 4px;
}
.border-radius-8 {
border-radius: 8px;
}
.border-radius-16 {
border-radius: 16px;
}
// -----------------------------------------------------------------------------------------------------
// @ Cursor helpers
// -----------------------------------------------------------------------------------------------------
.cursor-pointer {
cursor: pointer;
}
.cursor-default {
cursor: default;
}

View File

@ -1,26 +0,0 @@
i,
mat-icon {
font-size: 24px;
width: 24px;
height: 24px;
min-width: 24px;
min-height: 24px;
line-height: 24px;
@each $breakpoint, $materialBreakpoint in $helper-breakpoints {
@include media-breakpoint($materialBreakpoint) {
$infix: if($materialBreakpoint == null, '', '-#{$breakpoint}');
@for $size from 2 through 128 {
&.s#{$infix}-#{$size * 2} {
font-size: #{($size * 2) + 'px'} !important;
width: #{($size * 2) + 'px'} !important;
height: #{($size * 2) + 'px'} !important;
min-width: #{($size * 2) + 'px'} !important;
min-height: #{($size * 2) + 'px'} !important;
line-height: #{($size * 2) + 'px'} !important;
}
}
}
}
}

View File

@ -1,450 +0,0 @@
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
html {
line-height: 1.15; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main {
/* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: sans-serif; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type='button']:-moz-focusring,
[type='reset']:-moz-focusring,
[type='submit']:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* 1. Add the correct display in IE 9-.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type='checkbox'],
[type='radio'] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
*/
[type='search']::-webkit-search-cancel-button,
[type='search']::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
*/
details, /* 1 */
menu {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Scripting
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/
template {
display: none;
}
/* Hidden
========================================================================== */
/**
* Add the correct display in IE 10-.
*/
[hidden] {
display: none;
}

View File

@ -1,22 +0,0 @@
body:not(.is-mobile) {
::-webkit-scrollbar {
width: 12px;
height: 12px;
background-color: rgba(0, 0, 0, 0);
}
::-webkit-scrollbar:hover {
background-color: rgba(0, 0, 0, 0.12);
}
::-webkit-scrollbar-thumb {
border: 2px solid transparent;
box-shadow: inset 0 0 0 12px rgba(0, 0, 0, 0.37);
border-radius: 12px;
}
::-webkit-scrollbar-thumb:active {
box-shadow: inset 0 0 0 12px rgba(0, 0, 0, 0.54);
border-radius: 12px;
}
}

View File

@ -5,13 +5,7 @@
@include mat-core();
// Partials
// @import 'partials/breakpoints';
// @import 'partials/forms';
// @import 'partials/general';
// @import 'partials/helpers';
// @import 'partials/icons';
// @import 'partials/normalize';
// @import 'partials/scrollbars';
@import 'partials/material-ui';
//creative
@import 'global/default';

View File

@ -1,56 +1,63 @@
import { EventType } from '@ucap-webmessenger/protocol-event';
import {
EventType,
EventJson,
FileEventJson,
MassTextEventJson
} from '@ucap-webmessenger/protocol-event';
import { FileType } from '@ucap-webmessenger/protocol-file';
import { JsonObject } from 'type-fest';
import { JsonAnalization } from '@ucap-webmessenger/api';
export class StringUtil {
public static convertFinalEventMessage(
eventType: EventType,
finalEventMessage: string
finalEventMessage: EventJson
): string | null {
let eventMessage: string = null;
switch (eventType) {
case EventType.Join:
case EventType.Exit:
case EventType.RenameRoom:
case EventType.NotificationForTimerRoom:
case EventType.GuideForRoomTimerChanged: {
/**
* .
* @description Edit with ui-chat > messages.component.ts
*/
return null;
}
case EventType.GuideForRoomTimerChanged:
{
/**
* .
* @description Edit with ui-chat > messages.component.ts
*/
}
break;
case EventType.Sticker:
finalEventMessage = '스티커';
eventMessage = '스티커';
break;
case EventType.File:
{
const contentJson = JSON.parse(finalEventMessage);
if (contentJson.FileType === FileType.Image) {
finalEventMessage = '이미지';
const m = finalEventMessage as FileEventJson;
if (FileType.Image === m.fileType) {
eventMessage = '이미지';
} else {
finalEventMessage = '첨부파일';
eventMessage = '첨부파일';
}
}
break;
case EventType.VideoConference:
finalEventMessage = '화상회의';
eventMessage = '화상회의';
break;
case EventType.MassText:
{
try {
const json: JsonObject | Error = JsonAnalization.receiveAnalization(
finalEventMessage
);
finalEventMessage = json.Content.toString();
} catch (e) {
finalEventMessage = '대용량 텍스트';
}
const m = finalEventMessage as MassTextEventJson;
eventMessage = m.content;
}
break;
default:
return finalEventMessage;
{
const m = finalEventMessage as string;
eventMessage = m;
}
break;
}
return eventMessage;
}
}

View File

@ -1,6 +1,6 @@
import { EventType } from '../types/event.type';
export interface Info {
export interface Info<T = {}> {
// 이벤트SEQ
seq: number;
// 이벤트타입
@ -11,6 +11,8 @@ export interface Info {
sendDate: string;
// 발신내용
sentMessage: string;
// // 발신내용
sentMessageJson?: T;
// 수신자수
receiverCount: number;
}
@ -25,7 +27,7 @@ export function isRecalled(eventType: EventType): boolean {
return EventType.RecalledMessage === eventType;
}
export function isRecallable(event: Info, userSeq: number): boolean {
export function isRecallable(event: Info<any>, userSeq: number): boolean {
return (
event.senderSeq === userSeq && event.type !== EventType.RecalledMessage
);

View File

@ -0,0 +1,9 @@
import { EventJsonDecoder } from './event-json';
export type CharacterEventJson = string;
export const decodeCharacterEventJson: EventJsonDecoder<CharacterEventJson> = (
message: string
) => {
return message as CharacterEventJson;
};

View File

@ -0,0 +1,124 @@
import { EventType } from '../../types/event.type';
import { FileEventJson, decodeFileEventJson } from './file.event-json';
import {
MassTextEventJson,
decodeMassTextEventJson
} from './mass-text.event-json';
import { StickerEventJson, decodeStickerEventJson } from './sticker.event-json';
import { PlanEventJson, decodePlanEventJson } from './plan.event-json';
import {
VideoConferenceEventJson,
decodeVideoConferenceEventJson
} from './video-conference.event-json';
import {
RenameRoomEventJson,
decodeRenameRoomEventJson
} from './rename-room.event-json';
import {
TranslationEventJson,
decodeTranslationEventJson
} from './translation.event-json';
import {
MassTranslationEventJson,
decodeMassTranslationEventJson
} from './mass-translation.event-json';
import {
GuideForRoomTimerChangedEventJson,
decodeGuideForRoomTimerChangedEventJson
} from './guide-for-room-timer-changed.event-json';
import { JoinEventJson, decodeJoinEventJson } from './join.event-json';
import {
CharacterEventJson,
decodeCharacterEventJson
} from './character.event-json';
import { ExitEventJson, decodeExitEventJson } from './exit.event-json';
import { LinkEventJson, decodeLinkEventJson } from './link.event-json';
import {
RecalledMessageEventJson,
decodeRecalledMessageEventJson
} from './recalled-message.event-json';
import {
VideoStreammingEventJson,
decodeVideoStreammingEventJson
} from './video-streamming.event-json';
import {
NotificationForTimerRoomEventJson,
decodeNotificationForTimerRoomEventJson
} from './notification-for-timer-room.event-json';
export type EventJson =
| string
| string[]
| JoinEventJson
| CharacterEventJson
| ExitEventJson
| FileEventJson
| LinkEventJson
| MassTextEventJson
| RecalledMessageEventJson
| StickerEventJson
| PlanEventJson
| VideoConferenceEventJson
| RenameRoomEventJson
| NotificationForTimerRoomEventJson
| TranslationEventJson
| MassTranslationEventJson
| VideoStreammingEventJson
| GuideForRoomTimerChangedEventJson;
export const decodeEventJson = (
eventType: EventType,
message: string
): EventJson => {
switch (eventType) {
case EventType.Join:
return decodeJoinEventJson(message);
case EventType.Character:
return decodeCharacterEventJson(message);
case EventType.File:
return decodeFileEventJson(message);
case EventType.Sticker:
return decodeStickerEventJson(message);
case EventType.MassText:
return decodeMassTextEventJson(message);
case EventType.Exit:
return decodeExitEventJson(message);
case EventType.Plan:
return decodePlanEventJson(message);
case EventType.VideoConference:
return decodeVideoConferenceEventJson(message);
case EventType.Link:
return decodeLinkEventJson(message);
case EventType.RenameRoom:
return decodeRenameRoomEventJson(message);
case EventType.Translation:
return decodeTranslationEventJson(message);
case EventType.MassTranslation:
return decodeMassTranslationEventJson(message);
case EventType.RecalledMessage:
return decodeRecalledMessageEventJson(message);
case EventType.GuideForRoomTimerChanged:
return decodeGuideForRoomTimerChangedEventJson(message);
case EventType.NotificationForiOSCapture:
return message;
case EventType.NotificationForTimerRoom:
return decodeNotificationForTimerRoomEventJson(message);
case EventType.Before2MonthsAgo:
return message;
case EventType.ForcedExit:
return message;
case EventType.ChatbotStart:
return message;
case EventType.ChatbotEnd:
return message;
case EventType.ChatbotSend:
return message;
case EventType.ChatbotSendMass:
return message;
case EventType.VideoStreamming:
return decodeVideoStreammingEventJson(message);
default:
return message;
}
};

View File

@ -0,0 +1 @@
export type EventJsonDecoder<T> = (message: string) => T;

View File

@ -0,0 +1,9 @@
import { EventJsonDecoder } from './event-json';
export type ExitEventJson = string;
export const decodeExitEventJson: EventJsonDecoder<ExitEventJson> = (
message: string
) => {
return message;
};

View File

@ -0,0 +1,52 @@
import { StatusCode, JsonAnalization } from '@ucap-webmessenger/api';
import { FileType } from '@ucap-webmessenger/protocol-file';
import { EventJsonDecoder } from './event-json';
export interface FileEventJson {
statusCode?: StatusCode;
errorMessage?: string;
roomSeq?: number;
fileName?: string;
fileExt?: string;
fileType?: FileType;
thumbUrl?: string;
attachmentSeq?: number;
attachmentSize?: number;
attachmentRegDate?: string;
imageWidth?: number;
imageHeight?: number;
companyCode?: string;
voiceTime?: string;
synappKey?: string;
}
export const decodeFileEventJson: EventJsonDecoder<FileEventJson> = (
message: string
) => {
try {
const json = JsonAnalization.receiveAnalization(message);
return {
statusCode: json.StatusCode,
errorMessage: json.ErrorMessage,
roomSeq: json.RoomID,
fileName: json.FileName,
fileExt: json.FileExt,
fileType: json.FileType,
thumbUrl: json.ThumbURL,
attachmentSeq: json.AttSEQ,
attachmentSize: json.AttSize,
attachmentRegDate: json.AttRegDate,
imageWidth: json.ImageWidth,
imageHeight: json.ImageHeight,
companyCode: json.CompanyCode,
voiceTime: json.VoiceTime,
synappKey: json.SynappKey
} as FileEventJson;
} catch (e) {
return {
statusCode: StatusCode.Fail,
errorMessage: e.toString()
} as FileEventJson;
}
};

View File

@ -0,0 +1,17 @@
import { EventJsonDecoder } from './event-json';
export interface GuideForRoomTimerChangedEventJson {
senderSeq?: number;
time?: number;
}
export const decodeGuideForRoomTimerChangedEventJson: EventJsonDecoder<
GuideForRoomTimerChangedEventJson
> = (message: string) => {
const v = message.split(',');
return {
senderSeq: Number(v[0]),
time: Number(v[1])
} as GuideForRoomTimerChangedEventJson;
};

View File

@ -0,0 +1,17 @@
import { EventJsonDecoder } from './event-json';
export interface JoinEventJson {
owner?: string;
inviter?: string[];
}
export const decodeJoinEventJson: EventJsonDecoder<JoinEventJson> = (
message: string
) => {
const v = message.split(',');
return {
owner: v[0],
inviter: v.slice(1)
} as JoinEventJson;
};

View File

@ -0,0 +1,9 @@
import { EventJsonDecoder } from './event-json';
export type LinkEventJson = string;
export const decodeLinkEventJson: EventJsonDecoder<LinkEventJson> = (
message: string
) => {
return message as LinkEventJson;
};

View File

@ -0,0 +1,33 @@
import { StatusCode, JsonAnalization } from '@ucap-webmessenger/api';
import { EventJsonDecoder } from './event-json';
export interface MassTextEventJson {
statusCode?: StatusCode;
errorMessage?: string;
roomSeq?: number;
massSeq?: number;
regDate?: string;
content?: string;
}
export const decodeMassTextEventJson: EventJsonDecoder<MassTextEventJson> = (
message: string
) => {
try {
const json = JsonAnalization.receiveAnalization(message);
return {
statusCode: json.StatusCode,
errorMessage: json.ErrorMessage,
roomSeq: json.RoomID,
massSeq: json.EventMassSeq,
regDate: json.RegDate,
content: json.Content
} as MassTextEventJson;
} catch (e) {
return {
statusCode: StatusCode.Fail,
errorMessage: e.toString()
} as MassTextEventJson;
}
};

View File

@ -0,0 +1,37 @@
import { StatusCode, JsonAnalization } from '@ucap-webmessenger/api';
import { EventJsonDecoder } from './event-json';
export interface MassTranslationEventJson {
statusCode?: StatusCode;
errorMessage?: string;
translationSeq?: number;
destLocale?: string;
roomSeq?: number;
regDate?: string;
original?: string;
translation?: string;
}
export const decodeMassTranslationEventJson: EventJsonDecoder<
MassTranslationEventJson
> = (message: string) => {
try {
const json = JsonAnalization.receiveAnalization(message);
return {
statusCode: json.StatusCode,
errorMessage: json.ErrorMessage,
translationSeq: json.EventTransSeq,
destLocale: json.DestLocale,
roomSeq: json.RoomID,
regDate: json.RegDate,
original: json.Original,
translation: json.Translation
} as MassTranslationEventJson;
} catch (e) {
return {
statusCode: StatusCode.Fail,
errorMessage: e.toString()
} as MassTranslationEventJson;
}
};

View File

@ -0,0 +1,9 @@
import { EventJsonDecoder } from './event-json';
export type NotificationForTimerRoomEventJson = string;
export const decodeNotificationForTimerRoomEventJson: EventJsonDecoder<
NotificationForTimerRoomEventJson
> = (message: string) => {
return message as NotificationForTimerRoomEventJson;
};

View File

@ -0,0 +1,30 @@
import { EventJsonDecoder } from './event-json';
import { JsonAnalization } from '@ucap-webmessenger/api';
export interface PlanEventJson {
planSeq?: number;
title?: string;
contents?: string;
date?: string;
endDate?: string;
active?: boolean;
}
export const decodePlanEventJson: EventJsonDecoder<PlanEventJson> = (
message: string
) => {
try {
const json = JsonAnalization.receiveAnalization(message);
return {
planSeq: json.planSeq,
title: json.title,
contents: json.contents,
date: json.date,
endDate: json.endDate,
chat: json.chat,
active: !!json.activeYn && 'Y' === json.activeYn ? true : false
} as PlanEventJson;
} catch (e) {
return {} as PlanEventJson;
}
};

View File

@ -0,0 +1,9 @@
import { EventJsonDecoder } from './event-json';
export type RecalledMessageEventJson = string;
export const decodeRecalledMessageEventJson: EventJsonDecoder<
RecalledMessageEventJson
> = (message: string) => {
return message as RecalledMessageEventJson;
};

View File

@ -0,0 +1,15 @@
import { EventJsonDecoder } from './event-json';
export interface RenameRoomEventJson {
requester?: string;
roomName?: string;
}
export const decodeRenameRoomEventJson: EventJsonDecoder<
RenameRoomEventJson
> = (message: string) => {
return {
requester: message.substring(0, message.indexOf(',')),
roomName: message.substring(message.indexOf(',') + 1)
} as RenameRoomEventJson;
};

View File

@ -0,0 +1,19 @@
import { EventJsonDecoder } from './event-json';
export interface StickerEventJson {
name?: string;
file?: string;
chat?: string;
}
export const decodeStickerEventJson: EventJsonDecoder<StickerEventJson> = (
message: string
) => {
const json = JSON.parse(message);
return {
name: json.name,
file: json.file,
chat: json.chat
} as StickerEventJson;
};

View File

@ -0,0 +1,27 @@
import { EventJsonDecoder } from './event-json';
import { JsonAnalization } from '@ucap-webmessenger/api';
export interface TranslationEventJson {
locale?: string;
original?: string;
translation?: string;
stickerName?: string;
stickerFile?: string;
}
export const decodeTranslationEventJson: EventJsonDecoder<
TranslationEventJson
> = (message: string) => {
try {
const json = JsonAnalization.receiveAnalization(message);
return {
locale: json.locale,
original: json.original,
translation: json.translation,
stickerName: json.stickername,
stickerFile: json.stickerfile
} as TranslationEventJson;
} catch (e) {
return {} as TranslationEventJson;
}
};

View File

@ -0,0 +1,32 @@
import { EventJsonDecoder } from './event-json';
import { JsonAnalization } from '@ucap-webmessenger/api';
export interface VideoConferenceEventJson {
conferenceSeq?: number;
title?: string;
contents?: string;
startDate?: string;
endDate?: string;
register?: string;
attendee?: string;
}
export const decodeVideoConferenceEventJson: EventJsonDecoder<
VideoConferenceEventJson
> = (message: string) => {
try {
const json = JsonAnalization.receiveAnalization(message);
return {
conferenceSeq: json.confSeq,
title: json.title,
contents: json.contents,
startDate: json.startDate,
endDate: json.endDate,
register: json.register,
attendee: json.attendee
} as VideoConferenceEventJson;
} catch (e) {
return {} as VideoConferenceEventJson;
}
};

View File

@ -0,0 +1,9 @@
import { EventJsonDecoder } from './event-json';
export type VideoStreammingEventJson = string;
export const decodeVideoStreammingEventJson: EventJsonDecoder<
VideoStreammingEventJson
> = (message: string) => {
return message as VideoStreammingEventJson;
};

View File

@ -12,6 +12,7 @@ import {
} from '@ucap-webmessenger/protocol';
import { EventType } from '../types/event.type';
import { Info } from '../models/info';
import { decodeEventJson, EventJson } from './event-json/codec';
export interface InfoRequest extends ProtocolRequest {
// 대화방SEQ(s)
@ -25,7 +26,7 @@ export interface InfoRequest extends ProtocolRequest {
export interface InfoData extends ProtocolStream {
// 대화방SEQ(s)
roomSeq: string;
infoList: Info[];
infoList: Info<EventJson>[];
}
export interface InfoResponse extends ProtocolResponse {
@ -52,17 +53,20 @@ export const encodeInfo: ProtocolEncoder<InfoRequest> = (req: InfoRequest) => {
export const decodeInfoData: ProtocolDecoder<InfoData> = (
message: ProtocolMessage
) => {
const infoList: Info[] = [];
const infoList: Info<EventJson>[] = [];
for (const body of message.bodyList) {
const info = body.split(BodyStringDivider);
if (info.length > 5) {
const eventType = info[1] as EventType;
infoList.push({
seq: Number(info[0]),
type: info[1] as EventType,
type: eventType,
senderSeq: Number(info[2]),
sendDate: info[3],
sentMessage: info[4],
sentMessageJson: decodeEventJson(eventType, info[4]),
receiverCount: Number(info[5])
});
}

View File

@ -12,6 +12,8 @@ import {
} from '@ucap-webmessenger/protocol';
import { EventType } from '../types/event.type';
import { PushStatus } from '../types/push-status.type';
import { EventJson, decodeEventJson } from './event-json/codec';
import { Info } from '../models/info';
export interface SendRequest extends ProtocolRequest {
// 0. 대화방SEQ(s)
@ -41,6 +43,8 @@ export interface SendResponse extends ProtocolResponse {
ForcedExitType: string;
// 요청자 이름(s)
senderName: string;
/** Decoded Info */
info?: Info<EventJson>;
}
export interface SendNotification extends ProtocolNotification {
@ -66,6 +70,8 @@ export interface SendNotification extends ProtocolNotification {
id?: string;
/** 회사코드(s) */
companyCode?: string;
/** Decoded Info */
info?: Info<EventJson>;
}
export const encodeSend: ProtocolEncoder<SendRequest> = (req: SendRequest) => {
@ -83,33 +89,63 @@ export const encodeSend: ProtocolEncoder<SendRequest> = (req: SendRequest) => {
export const decodeSend: ProtocolDecoder<SendResponse> = (
message: ProtocolMessage
) => {
const seq = message.bodyList[1];
const eventType = message.bodyList[2] as EventType;
const sendDate = message.bodyList[3];
const sentMessage = message.bodyList[4];
const receiverCount = message.bodyList[5] || 0;
return decodeProtocolMessage(message, {
roomSeq: message.bodyList[0],
seq: message.bodyList[1],
eventType: message.bodyList[2] as EventType,
sendDate: message.bodyList[3],
message: message.bodyList[4],
receiverCount: message.bodyList[5] || 0,
eventType,
sendDate,
message: sentMessage,
receiverCount,
pushStatus: message.bodyList[6] as PushStatus,
ForcedExitType: message.bodyList[7],
senderName: message.bodyList[8]
senderName: message.bodyList[8],
info: {
seq,
type: eventType,
senderSeq: message.senderSeq,
sendDate,
sentMessage,
sentMessageJson: decodeEventJson(eventType, sentMessage),
receiverCount
}
} as SendResponse);
};
export const decodeSendNotification: ProtocolDecoder<SendNotification> = (
message: ProtocolMessage
) => {
const seq = message.bodyList[1];
const eventType = message.bodyList[2] as EventType;
const sendDate = message.bodyList[3];
const sentMessage = message.bodyList[4];
const receiverCount = message.bodyList[5] || 0;
return decodeProtocolMessage(message, {
roomSeq: message.bodyList[0],
seq: message.bodyList[1],
eventType: message.bodyList[2] as EventType,
sendDate: message.bodyList[3],
message: message.bodyList[4],
receiverCount: message.bodyList[5] || 0,
seq,
eventType,
sendDate,
message: sentMessage,
receiverCount,
pushStatus: message.bodyList[6] as PushStatus,
ForcedExitType: message.bodyList[7],
senderName: message.bodyList[8],
id: message.bodyList[9],
companyCode: message.bodyList[10]
companyCode: message.bodyList[10],
info: {
seq,
type: eventType,
senderSeq: message.senderSeq,
sendDate,
sentMessage,
sentMessageJson: decodeEventJson(eventType, sentMessage),
receiverCount
}
} as SendNotification);
};

View File

@ -11,6 +11,27 @@ export * from './lib/protocols/push';
export * from './lib/protocols/read';
export * from './lib/protocols/send';
export * from './lib/protocols/event-json/event-json';
export * from './lib/protocols/event-json/character.event-json';
export * from './lib/protocols/event-json/exit.event-json';
export * from './lib/protocols/event-json/file.event-json';
export * from './lib/protocols/event-json/guide-for-room-timer-changed.event-json';
export * from './lib/protocols/event-json/join.event-json';
export * from './lib/protocols/event-json/link.event-json';
export * from './lib/protocols/event-json/mass-text.event-json';
export * from './lib/protocols/event-json/mass-translation.event-json';
export * from './lib/protocols/event-json/notification-for-timer-room.event-json';
export * from './lib/protocols/event-json/plan.event-json';
export * from './lib/protocols/event-json/recalled-message.event-json';
export * from './lib/protocols/event-json/rename-room.event-json';
export * from './lib/protocols/event-json/sticker.event-json';
export * from './lib/protocols/event-json/translation.event-json';
export * from './lib/protocols/event-json/video-conference.event-json';
export * from './lib/protocols/event-json/video-streamming.event-json';
export * from './lib/protocols/event-json/codec';
export * from './lib/services/event-protocol.service';
export * from './lib/types/event.type';

View File

@ -1,18 +1,18 @@
<div class="bubble-main">
<!--파일명에 따라 doc exe hwp ppt xls zip 으로 추가되고 나머지 파일 명은 file로 기간이 만료된 파일은 그뒤에 disable도 추가-->
<!-- <div class="file-img" [ngClass]="fileInfo.FileExt"></div> -->
<div [ngClass]="['mime-icon', 'light', 'ico-' + fileInfo.FileExt]">
<div [ngClass]="['mime-icon', 'light', 'ico-' + fileInfo.fileExt]">
<div class="ico"></div>
</div>
<ul class="file-info">
<li class="file-name">
{{ fileInfo.FileName }}
{{ fileInfo.fileName }}
</li>
<li class="file-size">
{{ fileInfo.AttSize | ucapBytes }}
{{ fileInfo.attachmentSize | ucapBytes }}
</li>
<li class="file-ext">
{{ fileInfo.FileExt }}
{{ fileInfo.fileExt }}
</li>
</ul>
</div>
@ -20,7 +20,7 @@
<ul *ngIf="expired" class="expired">
<li>기간이 만료된 파일입니다.</li>
</ul>
<ul *ngIf="!expired && fileInfo && fileInfo.AttSEQ">
<ul *ngIf="!expired && fileInfo && fileInfo.attachmentSeq">
<li>
<button mat-button (click)="onClickSave()">Save</button>
</li>

View File

@ -1,6 +1,6 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { FileInfo } from '../../models/file-info.json';
import { NGXLogger } from 'ngx-logger';
import { FileEventJson } from '@ucap-webmessenger/protocol-event';
@Component({
selector: 'ucap-chat-message-box-attach-file',
@ -9,7 +9,7 @@ import { NGXLogger } from 'ngx-logger';
})
export class AttachFileComponent implements OnInit {
@Input()
fileInfo: FileInfo;
fileInfo: FileEventJson;
@Input()
expired = false;

View File

@ -1,5 +1,5 @@
import { Component, OnInit, Input } from '@angular/core';
import { Info } from '@ucap-webmessenger/protocol-event';
import { Info, EventJson } from '@ucap-webmessenger/protocol-event';
import { DatePipe } from '@angular/common';
@Component({
@ -9,7 +9,7 @@ import { DatePipe } from '@angular/common';
})
export class DateSplitterComponent implements OnInit {
@Input()
message: Info;
message: Info<EventJson>;
dateInfo: string;

View File

@ -1,6 +1,6 @@
<ng-container
*ngIf="fileInfo && fileInfo.FileType"
[ngSwitch]="fileInfo.FileType"
*ngIf="fileInfo && fileInfo.fileType"
[ngSwitch]="fileInfo.fileType"
>
<ucap-chat-message-box-attach-file
*ngSwitchCase="FileType.File"

View File

@ -1,9 +1,12 @@
import { Component, OnInit, Output, Input, EventEmitter } from '@angular/core';
import { Info, InfoResponse } from '@ucap-webmessenger/protocol-event';
import {
Info,
InfoResponse,
FileEventJson
} from '@ucap-webmessenger/protocol-event';
import { StatusCode } from '@ucap-webmessenger/api';
import { FileType } from '@ucap-webmessenger/protocol-file';
import { NGXLogger } from 'ngx-logger';
import { FileInfo } from '../../models/file-info.json';
@Component({
selector: 'ucap-chat-message-box-file',
@ -12,27 +15,27 @@ import { FileInfo } from '../../models/file-info.json';
})
export class FileComponent implements OnInit {
@Input()
message: Info;
message: Info<FileEventJson>;
@Input()
eventInfoStatus: InfoResponse;
@Output()
save = new EventEmitter<{ fileInfo: FileInfo; type: string }>();
save = new EventEmitter<{ fileInfo: FileEventJson; type: string }>();
@Output()
imageViewer = new EventEmitter<FileInfo>();
imageViewer = new EventEmitter<FileEventJson>();
fileInfo?: FileInfo;
fileInfo?: FileEventJson;
errorMessage?: string;
FileType = FileType;
constructor(private logger: NGXLogger) {}
ngOnInit() {
const contentJson: FileInfo = JSON.parse(this.message.sentMessage);
if (contentJson.StatusCode === StatusCode.Success) {
this.fileInfo = contentJson;
if (StatusCode.Success === this.message.sentMessageJson.statusCode) {
this.fileInfo = this.message.sentMessageJson;
} else {
this.errorMessage = contentJson.ErrorMessage || '[Error] System Error!!';
this.errorMessage =
this.message.sentMessageJson.errorMessage || '[Error] System Error!!';
}
}
@ -47,7 +50,7 @@ export class FileComponent implements OnInit {
}
}
onClickImageViewer(fileInfo: FileInfo) {
onClickImageViewer(fileInfo: FileEventJson) {
this.imageViewer.emit(this.fileInfo);
}

View File

@ -1,3 +1,3 @@
<div class="bubble-main">
<img [src]="fileInfo.ThumbURL">
<div class="bubble-main">
<img [src]="fileInfo.thumbUrl" />
</div>

View File

@ -1,6 +1,6 @@
import { Component, OnInit, Input } from '@angular/core';
import { NGXLogger } from 'ngx-logger';
import { FileInfo } from '../../models/file-info.json';
import { FileEventJson } from '@ucap-webmessenger/protocol-event';
@Component({
selector: 'ucap-chat-message-box-image',
@ -9,7 +9,7 @@ import { FileInfo } from '../../models/file-info.json';
})
export class ImageComponent implements OnInit {
@Input()
fileInfo: FileInfo;
fileInfo: FileEventJson;
@Input()
expired = false;

View File

@ -1,6 +1,14 @@
import { Component, OnInit, Input } from '@angular/core';
import { NGXLogger } from 'ngx-logger';
import { Info, EventType } from '@ucap-webmessenger/protocol-event';
import {
Info,
EventType,
EventJson,
JoinEventJson,
RenameRoomEventJson,
NotificationForTimerRoomEventJson,
GuideForRoomTimerChangedEventJson
} from '@ucap-webmessenger/protocol-event';
@Component({
selector: 'ucap-chat-message-box-information',
@ -9,7 +17,7 @@ import { Info, EventType } from '@ucap-webmessenger/protocol-event';
})
export class InformationComponent implements OnInit {
@Input()
message: Info;
message: Info<EventJson>;
@Input()
senderName?: string;
@ -20,41 +28,47 @@ export class InformationComponent implements OnInit {
ngOnInit() {
switch (this.message.type) {
case EventType.Join:
let owner: string;
const inviter: string[] = [];
this.message.sentMessage.split(',').forEach((userName, idx) => {
if (idx === 0) {
owner = userName + '님';
} else {
{
const m = this.message as Info<JoinEventJson>;
const owner = m.sentMessageJson.owner + '님';
const inviter: string[] = [];
m.sentMessageJson.inviter.forEach((userName, idx) => {
inviter.push(userName + '님');
}
});
this.contents = `${owner}${inviter.join(',')}을 초대했습니다.`;
});
this.contents = `${owner}${inviter.join(',')}을 초대했습니다.`;
}
break;
case EventType.Exit:
this.contents = `${this.message.sentMessage}님이 퇴장하셨습니다.`;
{
const m = this.message as Info<JoinEventJson>;
this.contents = `${m.sentMessage}님이 퇴장하셨습니다.`;
}
break;
case EventType.RenameRoom:
this.contents = `${this.message.sentMessage.substring(
0,
this.message.sentMessage.indexOf(',')
)} '${this.message.sentMessage.substring(
this.message.sentMessage.indexOf(',') + 1
)}' .`;
{
const m = this.message as Info<RenameRoomEventJson>;
this.contents = `${m.sentMessageJson.requester}님이 대화방명을 '${m.sentMessageJson.roomName}'으로 변경하셨습니다.`;
}
break;
case EventType.NotificationForTimerRoom:
/**
* , .
*/
this.contents = this.message.sentMessage;
{
const m = this.message as Info<NotificationForTimerRoomEventJson>;
/**
* , .
*/
this.contents = m.sentMessage;
}
break;
case EventType.GuideForRoomTimerChanged:
const values = this.message.sentMessage.split(',');
if (values && values.length === 2) {
{
const m = this.message as Info<GuideForRoomTimerChangedEventJson>;
this.contents = `${
this.senderName
} .(${this.getCalcTimer(
Number(values[1]) * 1000
m.sentMessageJson.time * 1000
)})`;
}
break;

View File

@ -1,9 +1,7 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { Info } from '@ucap-webmessenger/protocol-event';
import { Info, MassTextEventJson } from '@ucap-webmessenger/protocol-event';
import { NGXLogger } from 'ngx-logger';
import { StatusCode } from '@ucap-webmessenger/api';
import { MassTextInfo } from '../../models/mass-talk-info.json';
import { StringUtil } from '@ucap-webmessenger/ui';
@Component({
selector: 'ucap-chat-message-box-mass',
@ -12,7 +10,7 @@ import { StringUtil } from '@ucap-webmessenger/ui';
})
export class MassComponent implements OnInit {
@Input()
message: Info;
message: Info<MassTextEventJson>;
@Output()
massDetail = new EventEmitter<number>();
@ -25,18 +23,16 @@ export class MassComponent implements OnInit {
ngOnInit() {
try {
const contentJson: MassTextInfo = StringUtil.receiveAnalization(
this.message.sentMessage
);
if (contentJson.StatusCode === StatusCode.Success) {
this.content = contentJson.Content;
if (StatusCode.Success === this.message.sentMessageJson.statusCode) {
this.content = this.message.sentMessageJson.content;
} else {
this.content = contentJson.ErrorMessage || '[Error] System Error!!';
this.content =
this.message.sentMessageJson.errorMessage || '[Error] System Error!!';
this.detailButteonShow = false;
}
if (!!contentJson.EventMassSeq) {
this.eventMassSeq = contentJson.EventMassSeq;
if (!!this.message.sentMessageJson.massSeq) {
this.eventMassSeq = this.message.sentMessageJson.massSeq;
} else {
this.detailButteonShow = false;
}

View File

@ -2,14 +2,12 @@
<div class="event-header">이벤트제목</div>
<ul class="event-info">
<li class="event-title">
이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀
</li>
<li class="event-date">
<span>날짜</span> 2019.09.30
</li>
<li class="event-time">
<span>시간</span>오후 10시
이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트
타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트 타일틀이벤트
타일틀이벤트 타일틀
</li>
<li class="event-date"><span>날짜</span> 2019.09.30</li>
<li class="event-time"><span>시간</span>오후 10시</li>
</ul>
<div class="btn-box">

View File

@ -9,4 +9,6 @@ export class ScheduleComponent implements OnInit {
constructor() {}
ngOnInit() {}
onClickSave(): void {}
}

View File

@ -1,5 +1,5 @@
import { Component, OnInit, Input } from '@angular/core';
import { Info } from '@ucap-webmessenger/protocol-event';
import { Info, StickerEventJson } from '@ucap-webmessenger/protocol-event';
import { NGXLogger } from 'ngx-logger';
import { StickerInfo } from '../../models/sticker-info.json';
@ -10,7 +10,7 @@ import { StickerInfo } from '../../models/sticker-info.json';
})
export class StickerComponent implements OnInit {
@Input()
message: Info;
message: Info<StickerEventJson>;
contentJson?: StickerInfo;
stickerUrl?: string;
@ -18,9 +18,8 @@ export class StickerComponent implements OnInit {
ngOnInit() {
try {
this.contentJson = JSON.parse(this.message.sentMessage);
if (!!this.contentJson.file) {
this.stickerUrl = `assets/sticker/sticker_s_${this.contentJson.file}.png`;
if (!!this.message.sentMessageJson.file) {
this.stickerUrl = `assets/sticker/sticker_s_${this.message.sentMessageJson.file}.png`;
}
} catch (e) {
this.logger.error(e);

View File

@ -1,6 +1,5 @@
import { Component, OnInit, Input } from '@angular/core';
import { Info } from '@ucap-webmessenger/protocol-event';
import { StringUtil } from '@ucap-webmessenger/ui';
import { Info, EventJson } from '@ucap-webmessenger/protocol-event';
@Component({
selector: 'ucap-chat-message-box-text',
@ -9,7 +8,7 @@ import { StringUtil } from '@ucap-webmessenger/ui';
})
export class TextComponent implements OnInit {
@Input()
message: Info;
message: Info<EventJson>;
test = `가<br>나<br >다<br/>라<br />마<br class=""/>바사`;
constructor() {}

View File

@ -1,11 +1,15 @@
<div class="translation-main">
<div class="original">
{{ message.sentMessage }}
{{ message.sentMessageJson.translation }}
</div>
<div class="translation">
<span class="language">Kor</span>
녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트
녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요
장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요
장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트
</div>
<div class="btn-box">
<ul>

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, Input } from '@angular/core';
import { Info, TranslationEventJson } from '@ucap-webmessenger/protocol-event';
@Component({
selector: 'ucap-chat-message-box-translation',
@ -6,6 +7,9 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./translation.component.scss']
})
export class TranslationComponent implements OnInit {
@Input()
message: Info<TranslationEventJson>;
constructor() {}
ngOnInit() {}

View File

@ -11,7 +11,8 @@ import {
import {
Info,
EventType,
InfoResponse
InfoResponse,
EventJson
} from '@ucap-webmessenger/protocol-event';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { UserInfo } from '@ucap-webmessenger/protocol-room';
@ -29,7 +30,7 @@ export class MessagesComponent implements OnInit {
@Input()
loginRes: LoginResponse;
@Input()
messages: Info[];
messages: Info<EventJson>[];
@Input()
eventInfoStatus?: InfoResponse;
@Input()
@ -50,7 +51,7 @@ export class MessagesComponent implements OnInit {
@Output()
contextMenu = new EventEmitter<{
event: MouseEvent;
message: Info;
message: Info<EventJson>;
}>();
EventType = EventType;
@ -94,7 +95,7 @@ export class MessagesComponent implements OnInit {
return '';
}
getUnreadCount(message: Info): string | number {
getUnreadCount(message: Info<EventJson>): string | number {
const unreadCnt = this.userInfos.filter(user => {
if (message.senderSeq === user.seq) {
// 본인 글은 unreadCount 에 포함하지 않는다.
@ -110,7 +111,7 @@ export class MessagesComponent implements OnInit {
* @description event , .
* Edit with reducers.ts / sync / updateRoomForNewEventMessage
*/
getIsInformation(info: Info) {
getIsInformation(info: Info<EventJson>) {
if (
info.type === EventType.Join ||
info.type === EventType.Exit ||
@ -166,7 +167,7 @@ export class MessagesComponent implements OnInit {
}
/** [Event] Context Menu */
onContextMenuMessage(event: MouseEvent, message: Info) {
onContextMenuMessage(event: MouseEvent, message: Info<EventJson>) {
this.contextMenu.emit({ event, message });
}
}

View File

@ -0,0 +1,18 @@
<div class="ucap-image-viewer-container">
<div class="ucap-image-viewer-header">
<span>Third Line</span>
<span class="ucap-image-viewer-spacer"></span>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example heart icon"
>favorite</mat-icon
>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example delete icon"
>delete</mat-icon
>
</div>
</div>

View File

@ -0,0 +1,13 @@
.ucap-image-viewer-container {
width: 100%;
height: 100%;
.ucap-image-viewer-header {
width: 100%;
height: 50px;
.ucap-image-viewer-spacer {
flex: 1 1 auto;
}
}
}

View File

@ -0,0 +1,27 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { FileViewerComponent } from './file-viewer.component';
describe('FileViewerComponent', () => {
let component: FileViewerComponent;
let fixture: ComponentFixture<FileViewerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [FileViewerComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FileViewerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ucapAnimations } from '../animations';
@Component({
selector: 'ucap-file-viewer',
templateUrl: './file-viewer.component.html',
styleUrls: ['./file-viewer.component.scss'],
animations: ucapAnimations
})
export class FileViewerComponent implements OnInit {
@Output()
closed = new EventEmitter<void>();
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,18 @@
<div class="ucap-image-viewer-container">
<mat-toolbar color="primary">
<span>Third Line</span>
<span class="ucap-image-viewer-spacer"></span>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example heart icon"
>favorite</mat-icon
>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example delete icon"
>delete</mat-icon
>
</mat-toolbar>
</div>

View File

@ -0,0 +1,4 @@
.ucap-image-viewer-container {
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,27 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { DocumentViewerComponent } from './document-viewer.component';
describe('DocumentViewerComponent', () => {
let component: DocumentViewerComponent;
let fixture: ComponentFixture<DocumentViewerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [DocumentViewerComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DocumentViewerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ucapAnimations } from '../../animations';
@Component({
selector: 'ucap-document-viewer',
templateUrl: './document-viewer.component.html',
styleUrls: ['./document-viewer.component.scss'],
animations: ucapAnimations
})
export class DocumentViewerComponent implements OnInit {
@Output()
closed = new EventEmitter<void>();
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,18 @@
<div class="ucap-image-viewer-container">
<mat-toolbar color="primary">
<span>Third Line</span>
<span class="ucap-image-viewer-spacer"></span>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example heart icon"
>favorite</mat-icon
>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example delete icon"
>delete</mat-icon
>
</mat-toolbar>
</div>

View File

@ -0,0 +1,4 @@
.ucap-image-viewer-container {
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,27 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ImageViewerComponent } from './image-viewer.component';
describe('ImageViewerComponent', () => {
let component: ImageViewerComponent;
let fixture: ComponentFixture<ImageViewerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ImageViewerComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ImageViewerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ucapAnimations } from '../../animations';
@Component({
selector: 'ucap-image-viewer',
templateUrl: './image-viewer.component.html',
styleUrls: ['./image-viewer.component.scss'],
animations: ucapAnimations
})
export class ImageViewerComponent implements OnInit {
@Output()
closed = new EventEmitter<void>();
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,18 @@
<div class="ucap-image-viewer-container">
<mat-toolbar color="primary">
<span>Third Line</span>
<span class="ucap-image-viewer-spacer"></span>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example heart icon"
>favorite</mat-icon
>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example delete icon"
>delete</mat-icon
>
</mat-toolbar>
</div>

View File

@ -0,0 +1,4 @@
.ucap-image-viewer-container {
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,27 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { SoundViewerComponent } from './sound-viewer.component';
describe('SoundViewerComponent', () => {
let component: SoundViewerComponent;
let fixture: ComponentFixture<SoundViewerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [SoundViewerComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SoundViewerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ucapAnimations } from '../../animations';
@Component({
selector: 'ucap-sound-viewer',
templateUrl: './sound-viewer.component.html',
styleUrls: ['./sound-viewer.component.scss'],
animations: ucapAnimations
})
export class SoundViewerComponent implements OnInit {
@Output()
closed = new EventEmitter<void>();
constructor() {}
ngOnInit() {}
}

View File

@ -0,0 +1,18 @@
<div class="ucap-image-viewer-container">
<mat-toolbar color="primary">
<span>Third Line</span>
<span class="ucap-image-viewer-spacer"></span>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example heart icon"
>favorite</mat-icon
>
<mat-icon
class="example-icon"
aria-hidden="false"
aria-label="Example delete icon"
>delete</mat-icon
>
</mat-toolbar>
</div>

View File

@ -0,0 +1,4 @@
.ucap-image-viewer-container {
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,27 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ImageViewerComponent } from './image-viewer.component';
describe('ImageViewerComponent', () => {
let component: ImageViewerComponent;
let fixture: ComponentFixture<ImageViewerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ImageViewerComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ImageViewerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { ucapAnimations } from '../../animations';
@Component({
selector: 'ucap-video-viewer',
templateUrl: './video-viewer.component.html',
styleUrls: ['./video-viewer.component.scss'],
animations: ucapAnimations
})
export class VideoViewerComponent implements OnInit {
@Output()
closed = new EventEmitter<void>();
constructor() {}
ngOnInit() {}
}

View File

@ -1,7 +1,19 @@
import { FileUploadQueueComponent } from './file-upload-queue.component';
import { FloatActionButtonComponent } from './float-action-button.component';
import { FileViewerComponent } from './file-viewer.component';
import { DocumentViewerComponent } from './file-viewer/document-viewer.component';
import { ImageViewerComponent } from './file-viewer/image-viewer.component';
import { SoundViewerComponent } from './file-viewer/sound-viewer.component';
import { VideoViewerComponent } from './file-viewer/video-viewer.component';
export const UI_COMMON_COMPONENTS = [
FileUploadQueueComponent,
FloatActionButtonComponent
FloatActionButtonComponent,
FileViewerComponent,
DocumentViewerComponent,
ImageViewerComponent,
SoundViewerComponent,
VideoViewerComponent
];

View File

@ -10,6 +10,7 @@ import { MatDialogModule } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatToolbarModule } from '@angular/material/toolbar';
import { DragDropModule } from '@angular/cdk/drag-drop';
@ -61,6 +62,7 @@ const SERVICES = [
MatIconModule,
MatProgressBarModule,
MatSnackBarModule,
MatToolbarModule,
MatTooltipModule,
DragDropModule
],

View File

@ -1,5 +1,3 @@
import { JsonObject } from 'type-fest';
export class StringUtil {
/**
* linefeed > <br>
@ -39,7 +37,7 @@ export class StringUtil {
* Json String Analization.
* @description Editing with json.util.ts
*/
public static receiveAnalization(jsonStr: string): JsonObject {
public static receiveAnalization(jsonStr: string): any {
const startJson = jsonStr.indexOf('{');
const endJson = jsonStr.lastIndexOf('}');