This commit is contained in:
khk 2020-01-10 12:06:49 +09:00
commit a80341d2ea
20 changed files with 345 additions and 99 deletions

View File

@ -616,7 +616,7 @@ ipcMain.on(ProcessChannel.Execute, (event: IpcMainEvent, ...args: any[]) => {
const executableName: string = args[0];
const binPath = __DEV__
? path.join(__dirname, '../../', 'config/build/win/bin/')
: path.join(__dirname, '..', '..', '/bin/');
: path.join(__dirname, '..', '..', '..', '/bin/');
const executablePath = __WIN32__
? path.join(binPath, `${executableName}.exe`)

View File

@ -12,7 +12,11 @@ import { FileEventJson } from '@ucap-webmessenger/protocol-event';
import { DeviceType, FileUtil, MimeUtil } from '@ucap-webmessenger/core';
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
import { take, map, finalize, tap } from 'rxjs/operators';
import { SnackBarService } from '@ucap-webmessenger/ui';
import {
SnackBarService,
AlertSnackbarComponent,
AlertSnackbarData
} from '@ucap-webmessenger/ui';
import { FileDownloadItem } from '@ucap-webmessenger/api';
import { CommonApiService } from '@ucap-webmessenger/api-common';
import { TranslateService } from '@ngx-translate/core';
@ -112,21 +116,35 @@ export class FileViewerDialogComponent implements OnInit, OnDestroy {
}
);
} else {
this.snackBarService.open(
this.translateService.instant(
'common.file.errors.failToSave'
),
this.translateService.instant('common.file.errors.label')
);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant(
'common.file.errors.failToSave'
),
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
}
})
.catch(reason => {
this.snackBarService.open(
this.translateService.instant(
'common.file.errors.failToSave'
),
this.translateService.instant('common.file.errors.label')
);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant(
'common.file.errors.failToSave'
),
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
});
})
.catch(reason => {

View File

@ -8,7 +8,11 @@
<mat-tab [aria-label]="MainMenu.Group">
<ng-template mat-tab-label>
<!--<mat-icon>group</mat-icon>-->
<div class="icon-item" matTooltip="Group" matTooltipPosition="after">
<div
class="icon-item"
matTooltip="{{ 'group.label' | translate }}"
matTooltipPosition="after"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
@ -37,7 +41,7 @@
}}"
matBadgeColor="accent"
matBadgePosition="above after"
matTooltip="Chat"
matTooltip="{{ 'chat.label' | translate }}"
matTooltipPosition="after"
>
<svg
@ -63,7 +67,7 @@
<!--<mat-icon>device_hub</mat-icon>-->
<div
class="icon-item"
matTooltip="Organization"
matTooltip="{{ 'organization.chart' | translate }}"
matTooltipPosition="after"
>
<svg
@ -100,7 +104,7 @@
}}"
matBadgeColor="accent"
matBadgePosition="above after"
matTooltip="Message"
matTooltip="{{ 'message.label' | translate }}"
matTooltipPosition="after"
>
<svg

View File

@ -17,7 +17,7 @@ import {
CreateChatDialogData,
CreateChatDialogResult
} from '@app/layouts/messenger/dialogs/chat/create-chat.dialog.component';
import { Subscription, Observable } from 'rxjs';
import { Subscription, Observable, merge } from 'rxjs';
import { Store, select } from '@ngrx/store';
import * as AppStore from '@app/store';
@ -49,7 +49,7 @@ import {
} from '@app/types';
import { MessageBoxComponent } from './left-sidenav/message.component';
import { environment } from '../../../../environments/environment';
import { TranslateService } from '@ngx-translate/core';
import { TranslateService, LangChangeEvent } from '@ngx-translate/core';
export enum MainMenu {
Group = 'GROUP',
@ -83,6 +83,8 @@ export class LeftSideComponent implements OnInit, OnDestroy {
@ViewChild('messageBoxComponent', { static: false })
messageBoxComponent: MessageBoxComponent;
onLangChangeSubscription: Subscription;
badgeChatUnReadCount: number;
badgeChatUnReadCountSubscription: Subscription;
badgeMessageUnReadCount$: Observable<number>;
@ -149,6 +151,14 @@ export class LeftSideComponent implements OnInit, OnDestroy {
this.setFabInitial(MainMenu.Group);
this.currentTabLable = MainMenu.Group;
this.onLangChangeSubscription = merge(
this.translateService.onLangChange,
this.translateService.onDefaultLangChange,
this.translateService.onTranslationChange
).subscribe(() => {
this.setFabInitial(this.currentTabLable);
});
}
ngOnDestroy(): void {
@ -158,6 +168,9 @@ export class LeftSideComponent implements OnInit, OnDestroy {
if (!!this.loginResSubscription) {
this.loginResSubscription.unsubscribe();
}
if (!!this.onLangChangeSubscription) {
this.onLangChangeSubscription.unsubscribe();
}
if (!!this.badgeMessageInterval) {
clearInterval(this.badgeMessageInterval);

View File

@ -20,7 +20,9 @@ import {
AlertDialogData,
AlertDialogResult,
FileUploadQueueComponent,
StringUtil
StringUtil,
AlertSnackbarComponent,
AlertSnackbarData
} from '@ucap-webmessenger/ui';
import { Store, select } from '@ngrx/store';
import { NGXLogger } from 'ngx-logger';
@ -1015,21 +1017,35 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
}
);
} else {
this.snackBarService.open(
this.translateService.instant(
'common.file.errors.failToSave'
),
this.translateService.instant('common.file.errors.label')
);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant(
'common.file.errors.failToSave'
),
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
}
})
.catch(reason => {
this.snackBarService.open(
this.translateService.instant(
'common.file.errors.failToSave'
),
this.translateService.instant('common.file.errors.label')
);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant(
'common.file.errors.failToSave'
),
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
});
})
.catch(reason => {
@ -1239,6 +1255,12 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
(message as Info<string>).sentMessage
)
) {
this.snackBarService.open(
this.translateService.instant(
'common.clipboard.results.copied'
),
'확인'
);
this.snackBarService.open(
this.translateService.instant(
'common.clipboard.results.copied'

View File

@ -9,7 +9,6 @@ import { Store, select } from '@ngrx/store';
import * as AppStore from '@app/store';
import { tap, map, take, finalize } from 'rxjs/operators';
import { Info, FileEventJson } from '@ucap-webmessenger/protocol-event';
import { FileUtil, MimeUtil, DeviceType } from '@ucap-webmessenger/core';
import { CommonApiService } from '@ucap-webmessenger/api-common';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
@ -23,7 +22,11 @@ import {
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native';
import { NGXLogger } from 'ngx-logger';
import { SnackBarService } from '@ucap-webmessenger/ui';
import {
SnackBarService,
AlertSnackbarComponent,
AlertSnackbarData
} from '@ucap-webmessenger/ui';
import { FileDownloadItem } from '@ucap-webmessenger/api';
import { ModuleConfig } from '@ucap-webmessenger/api-common';
import { _MODULE_CONFIG } from 'projects/ucap-webmessenger-api-common/src/lib/config/token';
@ -247,21 +250,35 @@ export class AlbumBoxComponent implements OnInit, OnDestroy {
}
);
} else {
this.snackBarService.open(
this.translateService.instant(
'common.file.errors.failToSave'
),
this.translateService.instant('common.file.errors.label')
);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant(
'common.file.errors.failToSave'
),
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
}
})
.catch(reason => {
this.snackBarService.open(
this.translateService.instant(
'common.file.errors.failToSave'
),
this.translateService.instant('common.file.errors.label')
);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant(
'common.file.errors.failToSave'
),
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
});
})
.catch(reason => {

View File

@ -24,7 +24,9 @@ import {
ConfirmDialogComponent,
ConfirmDialogResult,
ConfirmDialogData,
DateOptions
DateOptions,
AlertSnackbarComponent,
AlertSnackbarData
} from '@ucap-webmessenger/ui';
import { CommonApiService } from '@ucap-webmessenger/api-common';
import { EventType } from '@ucap-webmessenger/protocol-event';
@ -291,21 +293,35 @@ export class FileBoxComponent implements OnInit, OnDestroy {
}
);
} else {
this.snackBarService.open(
this.translateService.instant(
'common.file.errors.failToSave'
),
this.translateService.instant('common.file.errors.label')
);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant(
'common.file.errors.failToSave'
),
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
}
})
.catch(reason => {
this.snackBarService.open(
this.translateService.instant(
'common.file.errors.failToSave'
),
this.translateService.instant('common.file.errors.label')
);
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
data: {
html: this.translateService.instant(
'common.file.errors.failToSave'
),
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
});
})
.catch(reason => {

View File

@ -16,7 +16,9 @@ import {
SnackBarService,
AlertDialogComponent,
AlertDialogResult,
AlertDialogData
AlertDialogData,
AlertSnackbarComponent,
AlertSnackbarData
} from '@ucap-webmessenger/ui';
import {
DetailResponse,
@ -400,9 +402,18 @@ export class MessageDetailDialogComponent implements OnInit {
'common.file.errors.failToSaveSomeOfAll'
);
}
this.snackBarService.open(errMsg, '', {
this.snackBarService.openFromComponent<
AlertSnackbarComponent,
AlertSnackbarData
>(AlertSnackbarComponent, {
duration: 8000,
verticalPosition: 'bottom'
verticalPosition: 'bottom',
data: {
html: errMsg,
buttonText: this.translateService.instant(
'common.file.errors.label'
)
}
});
} else {
// 성공종료.

View File

@ -121,7 +121,7 @@
*ngIf="updateInfo$ | async as updateInfo"
mat-icon-button
class="button app-layout-native-title-bar-setting"
matTooltip="업데이트"
matTooltip="{{ 'update.label' | translate }}"
(click)="onClickUpdate()"
>
<svg
@ -134,7 +134,7 @@
stroke-width="1.5"
stroke-linecap="butt"
stroke-linejoin="round"
alt="업데이트"
alt="Update"
>
<circle cx="12" cy="12" r="3"></circle>
<path

View File

@ -301,6 +301,9 @@
"haveNoPermission": "You do not have SMS permissions."
}
},
"update": {
"label": "Update"
},
"notification": {
"titleChatEventArrived": "A message of chat has arrived.",
"titleMessageArrived": "A message has arrived."
@ -350,8 +353,8 @@
"errors": {
"label": "File errors",
"failToUpload": "File upload failed.",
"failToSave": "File save failed. Please 'Save As'.",
"failToSaveSomeOfAll": "Some of file(s) save failed. Please 'Save As'.",
"failToSave": "File save failed.<br/>Please 'Save As'.",
"failToSaveSomeOfAll": "Some of file(s) save failed.<br/>Please 'Save As'.",
"failToSpecifyPath": "Specifing of save path failed.",
"expired": "This file has expired",
"noPreview": "This file does not support preview.",
@ -407,6 +410,10 @@
"simpleView": "Simple View",
"preview": "Preview"
},
"languages": {
"ko": "Korean",
"en": "English"
},
"timezone": {
"Africa/Abidjan": "Africa/Abidjan",
"Africa/Accra": "Africa/Accra",

View File

@ -301,6 +301,9 @@
"haveNoPermission": "SMS 사용 권한이 없습니다."
}
},
"update": {
"label": "업데이트"
},
"notification": {
"titleChatEventArrived": "메세지가 도착했습니다.",
"titleMessageArrived": "쪽지가 도착했습니다."
@ -350,8 +353,8 @@
"errors": {
"label": "파일 에러",
"failToUpload": "파일 업로드에 실패하였습니다.",
"failToSave": "파일 저장에 실패하였습니다. '다른 이름으로 저장' 하십시요.",
"failToSaveSomeOfAll": "파일 저장 중 일부 파일이 실패하였습니다. '다른 이름으로 저장' 하십시요.",
"failToSave": "파일 저장에 실패하였습니다.<br/>'다른 이름으로 저장' 하십시요.",
"failToSaveSomeOfAll": "파일 저장 중 일부 파일이 실패하였습니다.<br/>'다른 이름으로 저장' 하십시요.",
"failToSpecifyPath": "저장경로 지정에 실패하였습니다.",
"expired": "기간이 만료된 파일입니다",
"noPreview": "미리보기를 지원하지 않는 파일입니다.",
@ -407,6 +410,10 @@
"simpleView": "간략 보기",
"preview": "미리 보기"
},
"languages": {
"ko": "한국어",
"en": "영어"
},
"timezone": {
"Africa/Abidjan": "아프리카/아비 장",
"Africa/Accra": "아프리카/아크라",

View File

@ -80,11 +80,11 @@
[value]="setting.locale"
(selectionChange)="onSelectionChangeLocale($event)"
>
<mat-option value="ko">
한국어 (대한민국)
</mat-option>
<mat-option value="en">
영어 (미국)
<mat-option
*ngFor="let language of languageList"
[value]="language.name"
>
{{ language.displayName }}
</mat-option>
</mat-select>
</mat-form-field>
@ -99,11 +99,11 @@
[value]="setting.hrInfoLocale"
(selectionChange)="onSelectionChangeHrInfoLocale($event)"
>
<mat-option value="ko">
한국어 (대한민국)
</mat-option>
<mat-option value="en">
영어 (미국)
<mat-option
*ngFor="let language of languageList"
[value]="language.name"
>
{{ language.displayName }}
</mat-option>
</mat-select>
</mat-form-field>
@ -111,7 +111,7 @@
<mat-divider></mat-divider>
<h1 mat-subheader>시간대</h1>
<h1 mat-subheader>{{ 'settings.genernal.timezone' | translate }}</h1>
<mat-list-item>
<mat-form-field fxFlexFill>
<mat-select

View File

@ -29,6 +29,11 @@ export interface TimezoneData {
name: string;
}
export interface LanguageData {
displayName: string;
name: string;
}
@Component({
selector: 'ucap-settings-general',
templateUrl: './general.component.html',
@ -53,6 +58,15 @@ export class GeneralComponent implements OnInit, OnDestroy {
// tslint:disable-next-line: variable-name
_timezoneList: TimezoneData[];
get languageList(): LanguageData[] {
return this._languageList;
}
set languageList(languageList: LanguageData[]) {
this._languageList = languageList;
}
// tslint:disable-next-line: variable-name
_languageList: LanguageData[];
langChangeSubscription: Subscription;
constructor(
@ -79,6 +93,7 @@ export class GeneralComponent implements OnInit, OnDestroy {
this.themeTabGroup.selectedIndex = themeIndex;
this.setTimezoneData();
this.setLanguageData();
this.langChangeSubscription = merge(
this.translateService.onLangChange,
@ -86,6 +101,7 @@ export class GeneralComponent implements OnInit, OnDestroy {
this.translateService.onTranslationChange
).subscribe(() => {
this.setTimezoneData();
this.setLanguageData();
});
}
@ -145,25 +161,35 @@ export class GeneralComponent implements OnInit, OnDestroy {
}
private setTimezoneData() {
this.translateService
.get('common.timezone')
.pipe(take(1))
.subscribe(timezoneData => {
let timezoneList: TimezoneData[] = [];
for (const name of moment.tz.names()) {
const displayName = `(UTC${moment.tz(name).format('Z')}) ${
timezoneData[name]
}`;
timezoneList.push({
displayName,
name
});
}
timezoneList = timezoneList.sort((a: TimezoneData, b: TimezoneData) => {
return a.displayName.localeCompare(b.displayName);
});
const timezoneData = this.translateService.instant('common.timezone');
this.timezoneList = timezoneList;
let timezoneList: TimezoneData[] = [];
for (const name of moment.tz.names()) {
const displayName = `(UTC${moment.tz(name).format('Z')}) ${
timezoneData[name]
}`;
timezoneList.push({
displayName,
name
});
}
timezoneList = timezoneList.sort((a: TimezoneData, b: TimezoneData) => {
return a.displayName.localeCompare(b.displayName);
});
this.timezoneList = timezoneList;
}
private setLanguageData() {
const languageData = this.translateService.instant('common.languages');
const languageList: LanguageData[] = [];
for (const key in languageData) {
if (languageData.hasOwnProperty(key)) {
languageList.push({ displayName: languageData[key], name: key });
}
}
this.languageList = languageList;
}
}

View File

@ -6,6 +6,7 @@ import {
MatSnackBarRef,
SimpleSnackBar
} from '@angular/material';
import { ComponentType } from '@angular/cdk/portal';
@Injectable({
providedIn: 'root'
@ -20,4 +21,11 @@ export class SnackBarService {
): MatSnackBarRef<SimpleSnackBar> {
return this.matSnackBar.open(message, action, config);
}
public openFromComponent<T, D = any>(
componentRef: ComponentType<T>,
config?: MatSnackBarConfig<D>
): MatSnackBarRef<T> {
return this.matSnackBar.openFromComponent<T>(componentRef, config);
}
}

View File

@ -0,0 +1,18 @@
<div fxFlex fxLayout="row" class="mat-simple-snackbar ng-star-inserted">
<span fxFlex #messageContainer></span>
<div
fxFlex="nogrow"
fxFlexAlign="center"
class="mat-simple-snackbar-action ng-star-inserted"
>
<button mat-stroked-button (click)="onClickConfirm()">
<ng-container
*ngIf="data.buttonText; then buttonText; else default"
></ng-container>
<ng-template #buttonText>{{ data.buttonText }}</ng-template>
<ng-template #default>{{
'common.messages.confirm' | translate
}}</ng-template>
</button>
</div>
</div>

View File

@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AlertSnackbarComponent } from './alert.snackbar.component';
describe('ui::AlertSnackbarComponent', () => {
let component: AlertSnackbarComponent;
let fixture: ComponentFixture<AlertSnackbarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AlertSnackbarComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AlertSnackbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,48 @@
import {
Component,
OnInit,
Inject,
ViewChild,
ElementRef
} from '@angular/core';
import {
MatDialogRef,
MAT_DIALOG_DATA,
MAT_SNACK_BAR_DATA,
MatSnackBarRef
} from '@angular/material';
export interface AlertSnackbarData {
html: string;
buttonText?: string;
}
// tslint:disable-next-line: no-empty-interface
export interface AlertSnackbarResult {}
@Component({
selector: 'ucap-ui-alert-snackbar',
templateUrl: './alert.snackbar.component.html',
styleUrls: ['./alert.snackbar.component.scss']
})
export class AlertSnackbarComponent implements OnInit {
@ViewChild('messageContainer', { static: true })
messageContainer: ElementRef;
tempAgeLimits = [];
constructor(
public dialogRef: MatSnackBarRef<AlertSnackbarComponent>,
@Inject(MAT_SNACK_BAR_DATA) public data: AlertSnackbarData
) {}
ngOnInit(): void {
if (!!this.data.html) {
this.messageContainer.nativeElement.innerHTML = this.data.html;
}
}
onClickConfirm(): void {
this.dialogRef.dismiss();
}
}

View File

@ -75,6 +75,7 @@ import {
} from './pipes/string.pipe';
import { ClickDebounceDirective } from './directives/click-debounce.directive';
import { TranslationSectionComponent } from './components/translation-section.component';
import { AlertSnackbarComponent } from './snackbars/alert.snackbar.component';
const COMPONENTS = [
FileUploadQueueComponent,
@ -94,7 +95,11 @@ const COMPONENTS = [
SoundViewerComponent,
VideoViewerComponent
];
const DIALOGS = [AlertDialogComponent, ConfirmDialogComponent];
const DIALOGS = [
AlertDialogComponent,
ConfirmDialogComponent,
AlertSnackbarComponent
];
const DIRECTIVES = [
ClickOutsideDirective,
FileUploadForDirective,

View File

@ -37,6 +37,8 @@ export * from './lib/services/translate.service';
export * from './lib/services/date.service';
export * from './lib/services/paginator-intl.service';
export * from './lib/snackbars/alert.snackbar.component';
export * from './lib/types/file-viewer.type';
export * from './lib/utils/string.util';