Add date and datetime detail field components

- Add base date time component with common methods
- Add Components
- Register components in dynamic components manifest
- Add sample usage to list view
- Add karma/jasmine tests
This commit is contained in:
Clemente Raposo 2020-05-29 17:18:33 +01:00 committed by Dillon-Brown
parent 21a831e9f3
commit feb9175f22
20 changed files with 464 additions and 116 deletions

View file

@ -0,0 +1,58 @@
import {BaseFieldComponent} from './base-field.component';
import {combineLatest} from 'rxjs';
import {map} from 'rxjs/operators';
import {UserPreferenceMap, UserPreferenceStore} from '@store/user-preference/user-preference.store';
import {SystemConfigMap, SystemConfigStore} from '@store/system-config/system-config.store';
export class BaseDateTimeComponent extends BaseFieldComponent {
preferences$ = this.userPreferences.userPreferences$;
configs$ = this.systemConfig.configs$;
vm$ = combineLatest([this.configs$, this.preferences$]).pipe(
map(([configs, preferences]) => ({
configs,
preferences,
}))
);
constructor(
protected userPreferences: UserPreferenceStore,
protected systemConfig: SystemConfigStore
) {
super();
}
getDateFormat(preferences: UserPreferenceMap, configs: SystemConfigMap): string {
if (preferences && preferences.date_format) {
return preferences.date_format;
}
if (configs && configs.date_format) {
return configs.date_format.value;
}
return 'yyyy-mm-dd';
}
getTimeFormat(preferences: UserPreferenceMap, configs: SystemConfigMap): string {
let format = 'HH:mm:ss';
if (preferences && preferences.time_format) {
format = preferences.time_format;
} else if (configs && configs.time_format) {
format = configs.time_format.value;
}
return format.replace('aaaaaa', 'aaaaa\'m\'');
}
getDateTimeFormat(preferences: UserPreferenceMap, configs: SystemConfigMap): string {
const dateFormat = this.getDateFormat(preferences, configs);
const timeFormat = this.getTimeFormat(preferences, configs);
return dateFormat + ' ' + timeFormat;
}
}

View file

@ -0,0 +1,3 @@
<ng-container *ngIf="(vm$ | async) as vm">
{{value | date:getDateFormat(vm.preferences, vm.configs)}}
</ng-container>

View file

@ -0,0 +1,117 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component} from '@angular/core';
import {DateDetailFieldComponent} from '@fields/date/templates/detail/date.component';
import {distinctUntilChanged} from 'rxjs/operators';
import {BehaviorSubject, of} from 'rxjs';
import {CommonModule} from '@angular/common';
import {UserPreferenceStore} from '@store/user-preference/user-preference.store';
import {SystemConfigStore} from '@store/system-config/system-config.store';
@Component({
selector: 'date-detail-field-test-host-component',
template: '<scrm-date-detail [value]="value"></scrm-date-detail>'
})
class DateDetailFieldTestHostComponent {
value = '2020-05-01';
}
describe('DateDetailFieldComponent', () => {
let testHostComponent: DateDetailFieldTestHostComponent;
let testHostFixture: ComponentFixture<DateDetailFieldTestHostComponent>;
const preferences = new BehaviorSubject({
// eslint-disable-next-line camelcase, @typescript-eslint/camelcase
date_format: 'yyyy-MM-dd',
});
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
DateDetailFieldTestHostComponent,
DateDetailFieldComponent,
],
imports: [
CommonModule
],
providers: [
{
provide: UserPreferenceStore, useValue: {
userPreferences$: preferences.asObservable().pipe(distinctUntilChanged())
}
},
{
provide: SystemConfigStore, useValue: {
configs$: of({
// eslint-disable-next-line camelcase, @typescript-eslint/camelcase
date_format: {
id: '/docroot/api/system-configs/date_format',
_id: 'date_format',
value: 'dd.MM.yyyy',
items: []
}
})
}
}
],
}).compileComponents();
testHostFixture = TestBed.createComponent(DateDetailFieldTestHostComponent);
testHostComponent = testHostFixture.componentInstance;
testHostFixture.detectChanges();
}));
it('should create', () => {
expect(testHostComponent).toBeTruthy();
});
it('should have user preferences based formatted date', () => {
expect(testHostComponent).toBeTruthy();
preferences.next({
// eslint-disable-next-line camelcase, @typescript-eslint/camelcase
date_format: 'yyyy-MM-dd',
});
testHostComponent.value = '2020-04-14';
testHostFixture.detectChanges();
expect(testHostFixture.nativeElement.textContent).toContain('2020-04-14');
});
it('should have custom formatted date', () => {
expect(testHostComponent).toBeTruthy();
preferences.next({
// eslint-disable-next-line camelcase, @typescript-eslint/camelcase
date_format: 'yyyy/MM/dd',
});
testHostComponent.value = '2020-03-15';
testHostFixture.detectChanges();
expect(testHostFixture.nativeElement.textContent).toContain('2020/03/15');
});
it('should have system config based formatted date', () => {
expect(testHostComponent).toBeTruthy();
preferences.next({
// eslint-disable-next-line camelcase, @typescript-eslint/camelcase
date_format: null,
});
testHostComponent.value = '2020-02-16';
testHostFixture.detectChanges();
testHostFixture.detectChanges();
expect(testHostFixture.nativeElement.textContent).toContain('16.02.2020');
});
});

View file

@ -0,0 +1,19 @@
import {Component,} from '@angular/core';
import {BaseDateTimeComponent} from '@fields/base/base-datetime.component';
import {UserPreferenceStore} from '@store/user-preference/user-preference.store';
import {SystemConfigStore} from '@store/system-config/system-config.store';
@Component({
selector: 'scrm-date-detail',
templateUrl: './date.component.html',
styleUrls: []
})
export class DateDetailFieldComponent extends BaseDateTimeComponent {
constructor(
protected userPreferences: UserPreferenceStore,
protected systemConfig: SystemConfigStore
) {
super(userPreferences, systemConfig);
}
}

View file

@ -0,0 +1,16 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {AppManagerModule} from '@base/app-manager/app-manager.module';
import {DateDetailFieldComponent} from '@fields/date/templates/detail/date.component';
@NgModule({
declarations: [DateDetailFieldComponent],
exports: [DateDetailFieldComponent],
imports: [
CommonModule,
AppManagerModule.forChild(DateDetailFieldComponent)
]
})
export class DateDetailFieldModule {
}

View file

@ -1 +0,0 @@
{{ data.fieldValue }}

View file

@ -1,21 +0,0 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {DateListFieldsComponent} from './date.component';
describe('DateListFieldsComponent', () => {
let component: DateListFieldsComponent;
let fixture: ComponentFixture<DateListFieldsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [DateListFieldsComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DateListFieldsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
});

View file

@ -1,17 +0,0 @@
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'scrm-date-list',
templateUrl: './date.component.html',
styleUrls: []
})
export class DateListFieldsComponent implements OnInit {
data: any = [];
constructor() {
}
ngOnInit() {
}
}

View file

@ -1,15 +0,0 @@
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AppManagerModule } from '../../../../src/app-manager/app-manager.module';
import { DateListFieldsComponent } from './date.component';
@NgModule({
declarations: [DateListFieldsComponent],
exports: [DateListFieldsComponent],
imports: [
CommonModule,
AppManagerModule.forChild(DateListFieldsComponent)
]
})
export class DateListFieldsModule {}

View file

@ -0,0 +1,3 @@
<ng-container *ngIf="(vm$ | async) as vm">
{{value | date:getDateTimeFormat(vm.preferences, vm.configs)}}
</ng-container>

View file

@ -0,0 +1,169 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component} from '@angular/core';
import {DateTimeDetailFieldComponent} from './datetime.component';
import {CommonModule} from '@angular/common';
import {distinctUntilChanged} from 'rxjs/operators';
import {BehaviorSubject, of} from 'rxjs';
import {UserPreferenceStore} from '@store/user-preference/user-preference.store';
import {SystemConfigStore} from '@store/system-config/system-config.store';
@Component({
selector: 'datetime-detail-field-test-host-component',
template: '<scrm-datetime-detail [value]="value"></scrm-datetime-detail>'
})
class DateTimeDetailFieldTestHostComponent {
value = '2020-05-01 23:23:23';
}
describe('DatetimeDetailFieldComponent', () => {
let testHostComponent: DateTimeDetailFieldTestHostComponent;
let testHostFixture: ComponentFixture<DateTimeDetailFieldTestHostComponent>;
/* eslint-disable camelcase, @typescript-eslint/camelcase */
const preferences = new BehaviorSubject({
date_format: 'yyyy-MM-dd',
time_format: 'HH:mm:ss',
});
/* eslint-enable camelcase, @typescript-eslint/camelcase */
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
DateTimeDetailFieldTestHostComponent,
DateTimeDetailFieldComponent,
],
imports: [
CommonModule
],
providers: [
{
provide: UserPreferenceStore, useValue: {
userPreferences$: preferences.asObservable().pipe(distinctUntilChanged())
}
},
{
/* eslint-disable camelcase, @typescript-eslint/camelcase */
provide: SystemConfigStore, useValue: {
configs$: of({
date_format: {
id: '/docroot/api/system-configs/date_format',
_id: 'date_format',
value: 'dd.MM.yyyy',
items: []
},
time_format: {
id: '/docroot/api/system-configs/time_format',
_id: 'time_format',
value: 'HH.mm.ss',
items: []
}
})
/* eslint-enable camelcase, @typescript-eslint/camelcase */
}
}
],
}).compileComponents();
testHostFixture = TestBed.createComponent(DateTimeDetailFieldTestHostComponent);
testHostComponent = testHostFixture.componentInstance;
testHostFixture.detectChanges();
}));
it('should create', () => {
expect(testHostComponent).toBeTruthy();
});
it('should have user preferences based formatted datetime', () => {
expect(testHostComponent).toBeTruthy();
/* eslint-disable camelcase, @typescript-eslint/camelcase */
preferences.next({
date_format: 'yyyy-MM-dd',
time_format: 'HH:mm:ss',
});
/* eslint-enable camelcase, @typescript-eslint/camelcase */
testHostComponent.value = '2020-04-14 21:11:01';
testHostFixture.detectChanges();
expect(testHostFixture.nativeElement.textContent).toContain('2020-04-14 21:11:01');
});
it('should have custom formatted datetime', () => {
expect(testHostComponent).toBeTruthy();
/* eslint-disable camelcase, @typescript-eslint/camelcase */
preferences.next({
date_format: 'yyyy/MM/dd',
time_format: 'HH-mm',
});
/* eslint-enable camelcase, @typescript-eslint/camelcase */
testHostComponent.value = '2020-03-15 23:13:03';
testHostFixture.detectChanges();
expect(testHostFixture.nativeElement.textContent).toContain('2020/03/15 23-13');
});
it('should have system config based formatted datetime', () => {
expect(testHostComponent).toBeTruthy();
/* eslint-disable camelcase, @typescript-eslint/camelcase */
preferences.next({
date_format: null,
time_format: null,
});
/* eslint-enable camelcase, @typescript-eslint/camelcase */
testHostComponent.value = '2020-02-16 22:12:02';
testHostFixture.detectChanges();
testHostFixture.detectChanges();
expect(testHostFixture.nativeElement.textContent).toContain('16.02.2020 22.12.02');
});
it('should have formatted datetime with lowercase pm', () => {
expect(testHostComponent).toBeTruthy();
/* eslint-disable camelcase, @typescript-eslint/camelcase */
preferences.next({
date_format: 'yyyy/MM/dd',
time_format: 'hh.mm aaaaaa',
});
/* eslint-enable camelcase, @typescript-eslint/camelcase */
testHostComponent.value = '2020-02-16 22:12:02';
testHostFixture.detectChanges();
testHostFixture.detectChanges();
expect(testHostFixture.nativeElement.textContent).toContain('2020/02/16 10.12 pm');
});
it('should have formatted datetime with uppercase pm', () => {
expect(testHostComponent).toBeTruthy();
/* eslint-disable camelcase, @typescript-eslint/camelcase */
preferences.next({
date_format: 'yyyy/MM/dd',
time_format: 'hh.mm a',
});
/* eslint-enable camelcase, @typescript-eslint/camelcase */
testHostComponent.value = '2020-02-16 22:12:02';
testHostFixture.detectChanges();
testHostFixture.detectChanges();
expect(testHostFixture.nativeElement.textContent).toContain('2020/02/16 10.12 PM');
});
});

View file

@ -0,0 +1,19 @@
import {Component,} from '@angular/core';
import {BaseDateTimeComponent} from '@fields/base/base-datetime.component';
import {UserPreferenceStore} from '@store/user-preference/user-preference.store';
import {SystemConfigStore} from '@store/system-config/system-config.store';
@Component({
selector: 'scrm-datetime-detail',
templateUrl: './datetime.component.html',
styleUrls: []
})
export class DateTimeDetailFieldComponent extends BaseDateTimeComponent {
constructor(
protected userPreferences: UserPreferenceStore,
protected systemConfig: SystemConfigStore
) {
super(userPreferences, systemConfig);
}
}

View file

@ -0,0 +1,16 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {AppManagerModule} from '@base/app-manager/app-manager.module';
import {DateTimeDetailFieldComponent} from '@fields/datetime/templates/detail/datetime.component';
@NgModule({
declarations: [DateTimeDetailFieldComponent],
exports: [DateTimeDetailFieldComponent],
imports: [
CommonModule,
AppManagerModule.forChild(DateTimeDetailFieldComponent)
]
})
export class DateTimeDetailFieldModule {
}

View file

@ -1 +0,0 @@
{{ data.fieldValue }}

View file

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

View file

@ -1,17 +0,0 @@
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'scrm-datetime-list',
templateUrl: './datetime.component.html',
styleUrls: []
})
export class DatetimeListFieldsComponent implements OnInit {
data: any = {};
constructor() {
}
ngOnInit() {
}
}

View file

@ -1,15 +0,0 @@
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AppManagerModule } from '../../../../src/app-manager/app-manager.module';
import { DatetimeListFieldsComponent } from './datetime.component';
@NgModule({
declarations: [DatetimeListFieldsComponent],
exports: [DatetimeListFieldsComponent],
imports: [
CommonModule,
AppManagerModule.forChild(DatetimeListFieldsComponent)
]
})
export class DatetimeListFieldsModule {}

View file

@ -29,7 +29,11 @@ class FieldTestHostComponent {
{type: 'float', mode: 'detail', value: '1000.5', expected: '1,000.5'},
{type: 'float', mode: 'list', value: '1000.5', expected: '1,000.5'},
{type: 'phone', mode: 'detail', value: '+44 1111 123456', expected: '+44 1111 123456'},
{type: 'phone', mode: 'list', value: '+44 1111 123456', expected: '+44 1111 123456'}
{type: 'phone', mode: 'list', value: '+44 1111 123456', expected: '+44 1111 123456'},
{type: 'date', mode: 'detail', value: '2020-05-15 23:11:01', expected: '2020-05-15'},
{type: 'date', mode: 'list', value: '2020-05-16 23:11:01', expected: '2020-05-16'},
{type: 'datetime', mode: 'detail', value: '2020-05-14 23:11:01', expected: '2020-05-14 23:11:01'},
{type: 'datetime', mode: 'list', value: '2020-05-13 23:12:02', expected: '2020-05-13 23:12:02'}
];
}
@ -37,10 +41,14 @@ describe('FieldComponent', () => {
let testHostComponent: FieldTestHostComponent;
let testHostFixture: ComponentFixture<FieldTestHostComponent>;
/* eslint-disable camelcase, @typescript-eslint/camelcase */
const preferences = new BehaviorSubject({
num_grp_sep: ',',
dec_sep: '.',
date_format: 'yyyy-MM-dd',
time_format: 'HH:mm:ss',
});
/* eslint-enable camelcase, @typescript-eslint/camelcase */
beforeEach(async(() => {
TestBed.configureTestingModule({
@ -70,6 +78,18 @@ describe('FieldComponent', () => {
_id: 'default_decimal_seperator',
value: ',',
items: []
},
date_format: {
id: '/docroot/api/system-configs/date_format',
_id: 'date_format',
value: 'dd.MM.yyyy',
items: []
},
time_format: {
id: '/docroot/api/system-configs/time_format',
_id: 'time_format',
value: 'HH.mm.ss',
items: []
}
})
}

View file

@ -6,18 +6,26 @@ import {FloatDetailFieldModule} from '@fields/float/templates/detail/float.modul
import {FloatDetailFieldComponent} from '@fields/float/templates/detail/float.component';
import {PhoneDetailFieldModule} from '@fields/phone/templates/detail/phone.module';
import {PhoneDetailFieldComponent} from '@fields/phone/templates/detail/phone.component';
import {DateDetailFieldModule} from '@fields/date/templates/detail/date.module';
import {DateTimeDetailFieldModule} from '@fields/datetime/templates/detail/datetime.module';
import {DateDetailFieldComponent} from '@fields/date/templates/detail/date.component';
import {DateTimeDetailFieldComponent} from '@fields/datetime/templates/detail/datetime.component';
export const fieldModules = [
VarcharDetailFieldModule,
IntDetailFieldModule,
FloatDetailFieldModule,
PhoneDetailFieldModule
PhoneDetailFieldModule,
DateDetailFieldModule,
DateTimeDetailFieldModule
];
export const fieldComponents = [
VarcharDetailFieldComponent,
IntDetailFieldComponent,
FloatDetailFieldComponent,
PhoneDetailFieldComponent
PhoneDetailFieldComponent,
DateDetailFieldComponent,
DateTimeDetailFieldComponent
];
export const viewFieldsMap = {
@ -30,5 +38,9 @@ export const viewFieldsMap = {
'float.list': FloatDetailFieldComponent,
'float.detail': FloatDetailFieldComponent,
'phone.list': PhoneDetailFieldComponent,
'phone.detail': PhoneDetailFieldComponent
'phone.detail': PhoneDetailFieldComponent,
'date.list': DateDetailFieldComponent,
'date.detail': DateDetailFieldComponent,
'datetime.list': DateTimeDetailFieldComponent,
'datetime.detail': DateTimeDetailFieldComponent
};

View file

@ -20,6 +20,14 @@
TEST PHONE FIELD :
<scrm-field [mode]="'list'" [type]="'phone'" [value]="'+44 1111 123456'"></scrm-field>
</div>
<div>
TEST DATE FIELD:
<scrm-field [mode]="'list'" [type]="'date'" [value]="'2020-05-15 23:11:01'"></scrm-field>
</div>
<div>
TEST DATE TIME FIELD :
<scrm-field [mode]="'list'" [type]="'datetime'" [value]="'2020-05-15 23:11:01'"></scrm-field>
</div>
<scrm-list-header [module]="vm.appState.module"></scrm-list-header>
<scrm-list-container-ui></scrm-list-container-ui>
</div>