1 import {Injectable, Pipe, PipeTransform} from '@angular/core';
2 import {DatePipe, CurrencyPipe} from '@angular/common';
3 import {IdlService, IdlObject} from '@eg/core/idl.service';
4 import {OrgService} from '@eg/core/org.service';
7 * Format IDL vield values for display.
12 export interface FormatParams {
17 orgField?: string; // 'shortname' || 'name'
18 datePlusTime?: boolean;
21 @Injectable({providedIn: 'root'})
22 export class FormatService {
24 dateFormat = 'shortDate';
25 dateTimeFormat = 'short';
26 wsOrgTimezone: string = OpenSRF.tz;
29 private datePipe: DatePipe,
30 private currencyPipe: CurrencyPipe,
31 private idl: IdlService,
32 private org: OrgService
35 // Create an inilne polyfill for Number.isNaN, which is
36 // not available in PhantomJS for unit testing.
37 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
39 // "The following works because NaN is the only value
40 // in javascript which is not equal to itself."
41 Number.isNaN = (value: any) => {
42 return value !== value;
48 * Create a human-friendly display version of any field type.
50 transform(params: FormatParams): string {
51 const value = params.value;
53 if ( value === undefined
56 || Number.isNaN(value)) {
60 let datatype = params.datatype;
63 if (params.idlClass && params.idlField) {
64 datatype = this.idl.classes[params.idlClass]
65 .field_map[params.idlField].datatype;
67 // Assume it's a primitive value
75 if (typeof value !== 'object') {
76 return value + ''; // no fleshed value here
79 if (!params.idlClass || !params.idlField) {
80 // Without a full accounting of the field data,
81 // we can't determine the linked selector field.
86 this.idl.getLinkSelector(params.idlClass, params.idlField);
88 if (selector && typeof value[selector] === 'function') {
89 const val = value[selector]();
91 if (Array.isArray(val)) {
92 // Typically has_many links will not be fleshed,
93 // but in the off-chance the are, avoid displaying
94 // an array reference value.
105 const orgField = params.orgField || 'shortname';
106 const org = this.org.get(value);
107 return org ? org[orgField]() : '';
110 const date = new Date(value);
111 if (Number.isNaN(date.getTime())) {
112 console.error('Invalid date in format service', value);
115 let fmt = this.dateFormat || 'shortDate';
116 if (params.datePlusTime) {
117 fmt = this.dateTimeFormat || 'short';
120 if (params.idlField === 'dob') {
121 // special case: since dob is the only date column that the
122 // IDL thinks of as a timestamp, the date object comes over
123 // as a UTC value; apply the correct timezone rather than the
127 return this.datePipe.transform(date, fmt, tz);
130 return this.currencyPipe.transform(value);
133 // Slightly better than a bare 't' or 'f'.
134 // Note the caller is better off using an <eg-bool/> for
137 value === 't' || value === 1 ||
138 value === '1' || value === true
148 // Pipe-ify the above formating logic for use in templates
149 @Pipe({name: 'formatValue'})
150 export class FormatValuePipe implements PipeTransform {
151 constructor(private formatter: FormatService) {}
152 // Add other filter params as needed to fill in the FormatParams
153 transform(value: string, datatype: string): string {
154 return this.formatter.transform({value: value, datatype: datatype});