Revize 18dbad83
Přidáno uživatelem Václav Jirák před téměř 6 roky(ů)
webapp/package.json | ||
---|---|---|
23 | 23 |
"@angular/platform-browser-dynamic": "~7.2.0", |
24 | 24 |
"@angular/router": "~7.2.0", |
25 | 25 |
"@ng-bootstrap/ng-bootstrap": "^4.1.1", |
26 |
"@ngx-translate/core": "^11.0.1", |
|
27 |
"@ngx-translate/http-loader": "^4.0.0", |
|
26 | 28 |
"angular-calendar": "^0.27.5", |
27 | 29 |
"angularx-flatpickr": "^6.1.0", |
28 | 30 |
"core-js": "^2.5.4", |
webapp/src/app/app.module.ts | ||
---|---|---|
7 | 7 |
import { DashboardModule } from './dashboard/dashboard.module'; |
8 | 8 |
import { HeaderComponent } from './header/header.component'; |
9 | 9 |
import { MatDialogModule } from '@angular/material'; |
10 |
import {ProfileSettingsModule} from './profile-settings/profile-settings.module'; |
|
11 |
import {HttpClientModule} from '@angular/common/http'; |
|
12 |
import {EmployeesModule} from './employees/employees.module'; |
|
10 |
import { ProfileSettingsModule } from './profile-settings/profile-settings.module'; |
|
11 |
import { HttpClient, HttpClientModule } from '@angular/common/http'; |
|
12 |
import { EmployeesModule } from './employees/employees.module'; |
|
13 |
import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; |
|
14 |
import { TranslateHttpLoader } from '@ngx-translate/http-loader'; |
|
13 | 15 |
|
14 | 16 |
@NgModule({ |
15 | 17 |
declarations: [ |
... | ... | |
21 | 23 |
BrowserModule, |
22 | 24 |
HttpClientModule, |
23 | 25 |
AppRoutingModule, |
26 |
TranslateModule.forRoot({ |
|
27 |
loader: { |
|
28 |
provide: TranslateLoader, |
|
29 |
useFactory: HttpLoaderFactory, |
|
30 |
deps: [HttpClient] |
|
31 |
} |
|
32 |
}), |
|
24 | 33 |
DashboardModule, |
25 | 34 |
MatDialogModule, |
26 | 35 |
ProfileSettingsModule, |
... | ... | |
30 | 39 |
bootstrap: [AppComponent] |
31 | 40 |
}) |
32 | 41 |
export class AppModule { } |
42 |
|
|
43 |
export function HttpLoaderFactory(http: HttpClient) { |
|
44 |
return new TranslateHttpLoader(http, 'assets/i18n/', '.json'); |
|
45 |
} |
webapp/src/app/dashboard/employer-dashboard/employer-dashboard.component.ts | ||
---|---|---|
5 | 5 |
import {Requests} from '../../models/requests.model'; |
6 | 6 |
import {UserProfile} from '../../models/user-profile.model'; |
7 | 7 |
import {UserService} from '../../services/user.service'; |
8 |
import {ProfileService} from "../../services/profile.service"; |
|
8 |
import {ProfileService} from '../../services/profile.service'; |
|
9 |
import {TimeUnit} from '../../enums/common.enum'; |
|
9 | 10 |
|
10 | 11 |
@Component({ |
11 | 12 |
selector: 'app-employer-dashboard', |
... | ... | |
27 | 28 |
) { } |
28 | 29 |
|
29 | 30 |
ngOnInit() { |
30 |
this.profileService.getProfile() |
|
31 |
.subscribe((data: UserProfile) => this.profile = data); |
|
31 |
// this.profileService.getProfile() |
|
32 |
// .subscribe((data: UserProfile) => this.profile = data); |
|
33 |
// |
|
34 |
// this.usersService.getAuthorizationRequests() |
|
35 |
// .subscribe((data: Requests) => this.authorizationRequests = data); |
|
36 |
// |
|
37 |
// this.usersService.getVacationRequests() |
|
38 |
// .subscribe((data: Requests) => this.daysOffRequests = data); |
|
32 | 39 |
|
33 |
this.usersService.getAuthorizationRequests() |
|
34 |
.subscribe((data: Requests) => this.authorizationRequests = data); |
|
35 |
|
|
36 |
this.usersService.getVacationRequests() |
|
37 |
.subscribe((data: Requests) => this.daysOffRequests = data); |
|
40 |
// Tmp mock |
|
41 |
this.profile = { |
|
42 |
id: 1, |
|
43 |
name: { |
|
44 |
first: 'Jon', |
|
45 |
last: 'Doe', |
|
46 |
}, |
|
47 |
photo: 'http://mosaddek.com/theme/diverse/assets/img/user1.png', |
|
48 |
settings: { |
|
49 |
notification: new Date(2019, 3, 25, 18, 0) |
|
50 |
}, |
|
51 |
vacation: { |
|
52 |
value: 5, |
|
53 |
unit: TimeUnit.DAY, |
|
54 |
}, |
|
55 |
sickDay: { |
|
56 |
value: 10, |
|
57 |
unit: TimeUnit.DAY |
|
58 |
} |
|
59 |
}; |
|
38 | 60 |
} |
39 | 61 |
|
40 | 62 |
private userApproved(requestId: number, approved: boolean) { |
webapp/src/app/day-picker/day-picker.component.html | ||
---|---|---|
25 | 25 |
</div> |
26 | 26 |
</div> |
27 | 27 |
|
28 |
<!-- Refresh attribute for localization purposes (refresh component after change of language --> |
|
28 | 29 |
<mwl-calendar-month-view |
29 | 30 |
[viewDate]="viewDate" |
30 | 31 |
(dayClicked)="dayClicked($event.day)" |
31 | 32 |
weekStartsOn="1" |
32 | 33 |
[locale]="locale" |
34 |
[refresh]="localizationService.currentLanguage" |
|
33 | 35 |
> |
34 | 36 |
</mwl-calendar-month-view> |
35 | 37 |
</div> |
webapp/src/app/day-picker/day-picker.component.ts | ||
---|---|---|
1 | 1 |
import { Component, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core'; |
2 | 2 |
import { CalendarView } from 'angular-calendar'; |
3 |
import {LocalizationService} from '../localization/localization.service'; |
|
3 | 4 |
|
4 | 5 |
@Component({ |
5 | 6 |
selector: 'app-day-picker', |
... | ... | |
9 | 10 |
}) |
10 | 11 |
export class DayPickerComponent { |
11 | 12 |
|
12 |
// TODO Move to language service |
|
13 |
locale = 'cs'; |
|
13 |
private locale; |
|
14 | 14 |
|
15 | 15 |
// Type of calendar (constant) |
16 | 16 |
view: CalendarView = CalendarView.Month; |
... | ... | |
21 | 21 |
// EventEmitter informing about changes of selected date |
22 | 22 |
@Output() selectedDate = new EventEmitter<Date>(); |
23 | 23 |
|
24 |
constructor(private localizationService: LocalizationService) { |
|
25 |
this.locale = localizationService.defaultLanguage; |
|
26 |
localizationService.currentLanguage |
|
27 |
.subscribe((data) => { |
|
28 |
this.locale = data; |
|
29 |
}); |
|
30 |
} |
|
31 |
|
|
24 | 32 |
/** |
25 | 33 |
* Method that is invoked when user clicks on a day. |
26 | 34 |
* Sets selected date and emits event informing about new selected date. |
webapp/src/app/days-off-info/days-off-info.component.html | ||
---|---|---|
1 | 1 |
<div class="days-off-info-container"> |
2 | 2 |
|
3 |
<div class="component-header"> |
|
4 |
Zbývající volno |
|
3 |
<div class="component-header" translate> |
|
4 |
<!-- TODO--> |
|
5 |
<span translate>daysOffInfo.remaining</span> |
|
5 | 6 |
</div> |
6 | 7 |
|
7 | 8 |
<div class="days-off-type-container"> |
8 | 9 |
<span class="days-off-remaining">{{extraVacationRemaining.value}}</span> |
9 | 10 |
<!-- TODO vypsat jednotky (.unit)--> |
10 |
<span class="days-off-type">Extra dovolená</span>
|
|
11 |
<span class="days-off-type" translate>vacationType.vacation</span>
|
|
11 | 12 |
</div> |
12 | 13 |
|
13 | 14 |
<div class="days-off-type-container"> |
14 | 15 |
<span class="days-off-remaining">{{sickDaysRemaining.value}}</span> |
15 | 16 |
<!-- TODO vypsat jednotky (.unit)--> |
16 |
<span class="days-off-type">Sickdays</span>
|
|
17 |
<span class="days-off-type" translate>vacationType.sickday</span>
|
|
17 | 18 |
</div> |
18 | 19 |
|
19 | 20 |
</div> |
webapp/src/app/days-off-info/days-off-info.component.ts | ||
---|---|---|
1 | 1 |
import { Component, Input } from '@angular/core'; |
2 |
import {TimeUnit} from "../enums/common.enum"; |
|
2 |
import {TimeUnit} from '../enums/common.enum'; |
|
3 |
import {LocalizationService} from '../localization/localization.service'; |
|
3 | 4 |
|
4 | 5 |
@Component({ |
5 | 6 |
selector: 'app-days-off-info', |
... | ... | |
18 | 19 |
unit: TimeUnit; |
19 | 20 |
}; |
20 | 21 |
|
21 |
constructor() { } |
|
22 |
constructor(private localizationService: LocalizationService) { }
|
|
22 | 23 |
} |
webapp/src/app/days-off-info/days-off-info.module.ts | ||
---|---|---|
1 | 1 |
import { NgModule } from '@angular/core'; |
2 | 2 |
import { DaysOffInfoComponent } from './days-off-info.component'; |
3 |
import {TranslateModule} from '@ngx-translate/core'; |
|
3 | 4 |
|
4 | 5 |
@NgModule({ |
6 |
imports: [TranslateModule], |
|
5 | 7 |
declarations: [ DaysOffInfoComponent ], |
6 | 8 |
exports: [ DaysOffInfoComponent ] |
7 | 9 |
}) |
webapp/src/app/header/header.component.html | ||
---|---|---|
1 | 1 |
<div class="row header"> |
2 | 2 |
<img class="logo" src="../../assets/images/logo.png" /> |
3 |
<button class="user-info" (click)="onProfileClick()"> |
|
4 |
<img class="user-icon" src="../../assets/images/default-user.png"/> |
|
5 |
<span class="user-name">{{name}}</span> |
|
6 |
</button> |
|
3 |
<div class="language-and-user"> |
|
4 |
<button (click)="localizationService.switchLanguage('cs')">CS</button> |
|
5 |
<button (click)="localizationService.switchLanguage('en')">EN</button> |
|
6 |
<button class="user-info" (click)="onProfileClick()"> |
|
7 |
<img class="user-icon" src="../../assets/images/default-user.png"/> |
|
8 |
<span class="user-name">{{name}}</span> |
|
9 |
</button> |
|
10 |
</div> |
|
7 | 11 |
</div> |
webapp/src/app/header/header.component.sass | ||
---|---|---|
3 | 3 |
background-color: #3F425D |
4 | 4 |
padding-left: 10px |
5 | 5 |
|
6 |
.user-info |
|
7 |
height: 100% |
|
6 |
.language-and-user |
|
8 | 7 |
margin-left: auto |
9 | 8 |
margin-right: 0 |
9 |
|
|
10 |
.user-info |
|
11 |
height: 100% |
|
10 | 12 |
border: 0 |
11 | 13 |
background-color: transparent |
12 | 14 |
|
webapp/src/app/header/header.component.ts | ||
---|---|---|
3 | 3 |
import { ProfileSettingsComponent } from '../profile-settings/profile-settings.component'; |
4 | 4 |
import { ProfileService } from '../services/profile.service'; |
5 | 5 |
import { UserProfile } from '../models/user-profile.model'; |
6 |
import {LocalizationService} from "../localization/localization.service"; |
|
6 | 7 |
|
7 | 8 |
@Component({ |
8 | 9 |
selector: 'app-header', |
... | ... | |
16 | 17 |
|
17 | 18 |
constructor( |
18 | 19 |
private dialog: MatDialog, |
19 |
private profileService: ProfileService |
|
20 |
private profileService: ProfileService, |
|
21 |
private localizationService: LocalizationService |
|
20 | 22 |
) { |
21 |
profileService.getProfile() |
|
22 |
.subscribe((data: UserProfile) => this.notificationSettings = new Date(data.settings.notification)); |
|
23 |
// profileService.getProfile()
|
|
24 |
// .subscribe((data: UserProfile) => this.notificationSettings = new Date(data.settings.notification));
|
|
23 | 25 |
} |
24 | 26 |
|
25 | 27 |
onProfileClick(): void { |
webapp/src/app/localization/localization.service.ts | ||
---|---|---|
1 |
import { Injectable } from '@angular/core'; |
|
2 |
import { TranslateService } from '@ngx-translate/core'; |
|
3 |
import { registerLocaleData } from '@angular/common'; |
|
4 |
import localeEn from '@angular/common/locales/en'; |
|
5 |
import localeCs from '@angular/common/locales/cs'; |
|
6 |
import { Subject } from 'rxjs'; |
|
7 |
|
|
8 |
@Injectable({ |
|
9 |
providedIn: 'root' |
|
10 |
}) |
|
11 |
export class LocalizationService { |
|
12 |
readonly defaultLanguage = 'en'; |
|
13 |
|
|
14 |
currentLanguage: Subject<string>; |
|
15 |
|
|
16 |
constructor(private translate: TranslateService) { |
|
17 |
this.currentLanguage = new Subject<string>(); |
|
18 |
|
|
19 |
registerLocaleData(localeEn); |
|
20 |
registerLocaleData(localeCs); |
|
21 |
|
|
22 |
translate.setDefaultLang(this.defaultLanguage); |
|
23 |
} |
|
24 |
|
|
25 |
switchLanguage(lang: string) { |
|
26 |
this.translate.use(lang); |
|
27 |
this.currentLanguage.next(lang); |
|
28 |
} |
|
29 |
} |
webapp/src/app/services/profile.service.ts | ||
---|---|---|
12 | 12 |
constructor( |
13 | 13 |
private userService: UserService |
14 | 14 |
) { |
15 |
userService.getEmployeeProfile(1) |
|
16 |
.subscribe((data: UserProfile) => this.profile = data); |
|
15 |
// userService.getEmployeeProfile(1)
|
|
16 |
// .subscribe((data: UserProfile) => this.profile = data);
|
|
17 | 17 |
} |
18 | 18 |
|
19 | 19 |
getProfile(): Observable<UserProfile> { |
webapp/src/assets/i18n/cs.json | ||
---|---|---|
1 |
{ |
|
2 |
"daysOffInfo": { |
|
3 |
"remaining": "Zbývající dovolená" |
|
4 |
}, |
|
5 |
"vacationType": { |
|
6 |
"vacation": "Extra dovolená", |
|
7 |
"sickday": "Sickday" |
|
8 |
} |
|
9 |
} |
webapp/src/assets/i18n/en.json | ||
---|---|---|
1 |
{ |
|
2 |
"daysOffInfo": { |
|
3 |
"remaining": "Vacation remaining" |
|
4 |
}, |
|
5 |
"vacationType": { |
|
6 |
"vacation": "Extra vacation", |
|
7 |
"sickday": "Sickday" |
|
8 |
} |
|
9 |
} |
Také k dispozici: Unified diff
Re #7475 Implemented basic localization with usage examples