Skip to content
This repository has been archived by the owner on Mar 25, 2023. It is now read-only.

(closes #12) Add time format to settings #264

Merged
merged 4 commits into from
Jul 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"reflect-metadata": "^0.1.10",
"rxjs": "^5.1.0",
"uuid": "^3.1.0",
"zone.js": "^0.8.4"
"zone.js": "0.8.12"
},
"devDependencies": {
"@angular/cli": "1.1.3",
Expand Down
5 changes: 5 additions & 0 deletions src/app/events/event-list.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { SharedModule } from '../shared/shared.module';
import { EventListComponent } from './event-list.component';
import { Event } from './event.model';
import { EventService } from './event.service';
import { TimeFormat } from '../shared/services/language.service';


const eventServiceFixture = require('./event.service.fixture.json');
Expand Down Expand Up @@ -72,6 +73,10 @@ class MockLanguageService {
public getFirstDayOfWeek(): Observable<number> {
return Observable.of(0);
}

public getTimeFormat(): Observable<string | null> {
return Observable.of(TimeFormat.AUTO);
}
}

@Pipe({
Expand Down
34 changes: 26 additions & 8 deletions src/app/events/event-list.component.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { MdlDefaultTableModel } from '@angular-mdl/core';
import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { MdlDefaultTableModel } from '@angular-mdl/core';
import { Observable } from 'rxjs/Observable';

import { dateTimeFormat, formatIso } from '../shared/components/date-picker/dateUtils';
import { FilterService } from '../shared';
import { dateTimeFormat, formatIso } from '../shared/components/date-picker/dateUtils';
import { LanguageService } from '../shared/services';
import { TimeFormat } from '../shared/services/language.service';
import { Event } from './event.model';
import { EventService } from './event.service';
import { WithUnsubscribe } from '../utils/mixins/with-unsubscribe';

import moment = require('moment');

Expand All @@ -17,7 +19,7 @@ import moment = require('moment');
templateUrl: 'event-list.component.html',
styleUrls: ['event-list.component.scss']
})
export class EventListComponent implements OnInit {
export class EventListComponent extends WithUnsubscribe() implements OnInit {
public loading = false;
public tableModel: MdlDefaultTableModel;

Expand All @@ -27,6 +29,7 @@ export class EventListComponent implements OnInit {
public dateTimeFormat;
public dateStringifyDateTimeFormat;
public firstDayOfWeek: number;
public timeFormat: string;

public events: Array<Event>;
public selectedLevels: Array<string>;
Expand All @@ -45,20 +48,31 @@ export class EventListComponent implements OnInit {
private translate: TranslateService,
private languageService: LanguageService
) {
super();
this.firstDayOfWeek = this.locale === 'en' ? 0 : 1;
this.updateEvents = this.updateEvents.bind(this);
}

public ngOnInit(): void {
this.setDateTimeFormat();
this.translate.onLangChange.subscribe(() => this.setDateTimeFormat());
this.translate.onLangChange
.takeUntil(this.unsubscribe$)
.subscribe(() => this.setDateTimeFormat());
this.translate.get(['DESCRIPTION', 'LEVEL', 'TYPE', 'TIME'])
.subscribe(translations => this.initTableModel(translations));
this.initFilters();
this.getEvents({ reload: true });

this.languageService.getFirstDayOfWeek()
.subscribe(day => this.firstDayOfWeek = day);
Observable.forkJoin(
this.languageService.getFirstDayOfWeek(),
this.languageService.getTimeFormat()
)
.subscribe(([day, timeFormat]) => {
this.firstDayOfWeek = day;
this.timeFormat = timeFormat;
this.setDateTimeFormat();

this.getEvents({ reload: true });
});
}

public get locale(): string {
Expand Down Expand Up @@ -164,12 +178,16 @@ export class EventListComponent implements OnInit {
this.dateTimeFormat = Intl.DateTimeFormat;
}

const options = {
const options: Intl.DateTimeFormatOptions = {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
timeZoneName: 'short'
};

if (this.timeFormat !== TimeFormat.AUTO) {
options.hour12 = this.timeFormat === TimeFormat['12h'];
}
this.dateStringifyDateTimeFormat = new Intl.DateTimeFormat(this.locale, options);
}

Expand Down
13 changes: 13 additions & 0 deletions src/app/settings/settings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ <h5 class="no-margin">{{ 'FIRST_DAY_OF_WEEK' | translate }}</h5>
</mdl-option>
</mdl-select>
</div>
<div class="settings-control">
<h5 class="no-margin">{{ 'TIME_FORMAT' | translate }}</h5>
<mdl-select
[ngModel]="timeFormat"
[disabled]="updatingTimeFormat"
(change)="changeTimeFormat($event)"
>
<mdl-option
*ngFor="let format of timeFormats"
[value]="TimeFormat[format]"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If AUTO is set, selected value is not visible
screen shot 2017-07-16 at 16 20 52

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I know https://git.io/v9R69

>{{ format | translate }}</mdl-option>
</mdl-select>
</div>
<div class="settings-control">
<h5>{{ 'PALETTE' | translate }}</h5>
<div>
Expand Down
28 changes: 26 additions & 2 deletions src/app/settings/settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,29 @@ import { TranslateService } from '@ngx-translate/core';

import { Color, LanguageService, StyleService } from '../shared';
import { AuthService, NotificationService } from '../shared/services';
import { TimeFormat } from '../shared/services/language.service';
import { UserService } from '../shared/services/user.service';
import { WithUnsubscribe } from '../utils/mixins/with-unsubscribe';


@Component({
selector: 'cs-settings',
templateUrl: 'settings.component.html',
styleUrls: ['settings.component.scss']
})
export class SettingsComponent implements OnInit {
export class SettingsComponent extends WithUnsubscribe() implements OnInit {
public userId: string;
public accentColor: Color;
public firstDayOfWeek = 1;
public language: string;
public primaryColor: Color;
public primaryColors: Array<Color>;
public timeFormat: string = TimeFormat.AUTO;

public passwordUpdateForm: FormGroup;

public updatingFirstDayOfWeek = false;
public updatingTimeFormat = false;
public dayTranslations: {};
public loading = false;

Expand All @@ -39,6 +43,10 @@ export class SettingsComponent implements OnInit {
{ value: 1, text: 'MONDAY' }
];

public TimeFormat = TimeFormat;
// TODO replace when TypeScript 2.4 string enums land
public timeFormats = Object.keys(TimeFormat);

constructor(
private authService: AuthService,
private formBuilder: FormBuilder,
Expand All @@ -48,6 +56,7 @@ export class SettingsComponent implements OnInit {
private translateService: TranslateService,
private userService: UserService
) {
super();
this.userId = this.authService.userId;
}

Expand All @@ -57,7 +66,10 @@ export class SettingsComponent implements OnInit {
this.loadFirstDayOfWeek();
this.buildForm();
this.loadDayTranslations();
this.translateService.onLangChange.subscribe(() => this.loadDayTranslations());
this.loadTimeFormat();
this.translateService.onLangChange
.takeUntil(this.unsubscribe$)
.subscribe(() => this.loadDayTranslations());
}

public get accentColors(): Array<Color> {
Expand All @@ -78,6 +90,13 @@ export class SettingsComponent implements OnInit {
this.loadDayTranslations();
}

public changeTimeFormat(timeFormat: string): void {
this.updatingTimeFormat = true;
this.languageService.setTimeFormat(timeFormat)
.finally(() => this.updatingTimeFormat = false)
.subscribe();
}

public updatePrimaryColor(color: Color): void {
this.primaryColor = color;
if (this.primaryColor.value === this.accentColor.value) {
Expand Down Expand Up @@ -151,6 +170,11 @@ export class SettingsComponent implements OnInit {
.subscribe((day: number) => this.firstDayOfWeek = day);
}

private loadTimeFormat(): void {
this.languageService.getTimeFormat()
.subscribe(timeFormat => this.timeFormat = timeFormat);
}

private buildForm(): void {
this.passwordUpdateForm = this.formBuilder.group({
password: ['', Validators.required],
Expand Down
24 changes: 24 additions & 0 deletions src/app/shared/services/language.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import { UserService } from './user.service';

const DEFAULT_LANGUAGE = 'en';

export const TimeFormat = {
'12h': '12h',
'24h': '24h',
AUTO: 'auto'
};

@Injectable()
export class LanguageService {
constructor(
Expand Down Expand Up @@ -48,6 +54,24 @@ export class LanguageService {
});
}

public getTimeFormat(): Observable<string> {
return this.userService.readTag('timeFormat')
.map(timeFormat => {
switch (timeFormat) {
case TimeFormat['12h']:
case TimeFormat['24h']:
return timeFormat;
default: return TimeFormat.AUTO;
}
});
}

public setTimeFormat(timeFormat: string): Observable<string> {
return (timeFormat === TimeFormat.AUTO
? this.userService.removeTag('timeFormat')
: this.userService.writeTag('timeFormat', timeFormat)).mapTo(timeFormat);
}

private get defaultLanguage(): string {
const language = navigator.language && navigator.language.substr(0, 2);
if (language === 'ru' || language === 'en') {
Expand Down
5 changes: 5 additions & 0 deletions src/app/utils/mixins/contructor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type Constructor<T = {}> = new (...args: any[]) => T;
export class SimpleClass {
}


15 changes: 15 additions & 0 deletions src/app/utils/mixins/with-unsubscribe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Subject } from 'rxjs/Subject';
import { OnDestroy } from '@angular/core';
import { Constructor, SimpleClass } from './contructor';


export const WithUnsubscribe = <TBase extends Constructor<{}>>(Base: TBase = SimpleClass as TBase) => {
return class extends Base implements OnDestroy {
protected unsubscribe$ = new Subject<never>();

ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
};
};
4 changes: 4 additions & 0 deletions src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@
"LANGUAGE": "Interface Language",
"COLOR": "Color",
"FIRST_DAY_OF_WEEK": "First day of the week",
"TIME_FORMAT": "Time format",
"12h": "12-Hours Time",
"24h": "24-Hours Time",
"AUTO": "Auto",
"MONDAY": "Monday",
"SUNDAY": "Sunday",
"GROUP_BY_COLORS": "Group by colors",
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@
"LANGUAGE": "Язык Интерфейса",
"COLOR": "Цвет",
"FIRST_DAY_OF_WEEK": "Первый день недели",
"TIME_FORMAT": "Формат времени",
"12h": "12-часовой формат",
"24h": "24-часовой формат",
"AUTO": "Автоматически",
"MONDAY": "Понедельник",
"SUNDAY": "Воскресенье",
"GROUP_BY_COLORS": "Группировать по цветам",
Expand Down
1 change: 1 addition & 0 deletions src/polyfills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/finally';
import 'rxjs/add/operator/pluck';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/takeUntil';
import 'rxjs/add/operator/switchMapTo';
import 'rxjs/add/observable/merge';
import 'rxjs/add/observable/throw';
Expand Down