-
Notifications
You must be signed in to change notification settings - Fork 268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ACS-5857] Moment to Date-Fns Migration for adfMomentDate Pipe. #8924
Conversation
let service: DateFormatTranslationService; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need this block, the service does not use Translation or Root, and it has providedIn: root, so you don't need setting the "providers" section too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
a: 'A' | ||
}; | ||
|
||
convertMomentToDateFnsFormat(dateDisplayFormat: string): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
provide code comments for the public methods so that it gets to the generated documentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added comments
lib/core/src/lib/pipes/date.pipe.ts
Outdated
import { DateFormatTranslationService } from '../form/services/date-format-translation.service'; | ||
|
||
@Pipe({ name: 'adfDate' }) | ||
export class DatePipe implements PipeTransform { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the naming of class is going to clash with Angular DatePipe: https://angular.io/api/common/DatePipe
please use AdfDatePipe as the pipe name suggests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed
lib/core/src/lib/form/components/widgets/core/form-field.model.ts
Outdated
Show resolved
Hide resolved
@@ -19,9 +19,16 @@ import moment from 'moment'; | |||
import { FormFieldTypes } from './form-field-types'; | |||
import { FormFieldModel } from './form-field.model'; | |||
import { FormModel } from './form.model'; | |||
import { DateFormatTranslationService } from '../../../public-api'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incorrect import path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed import path
lib/core/src/lib/form/components/widgets/core/form-field.model.ts
Outdated
Show resolved
Hide resolved
return format(date, this.convertMomentToDateFnsFormat(dateFormat)); | ||
} | ||
|
||
parse(value: string, dateFormat: string, date = new Date()): Date { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function is confusing, why it takes date parameter and why it sets it to new date() ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there are no cases when you pass the date here, please use "new Date()" inside the "parse" call instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated to call new Date() inside parse itself.
const date = moment(newDateValue, this.field.dateDisplayFormat, true); | ||
if (date.isValid()) { | ||
this.field.value = date.format(this.field.dateDisplayFormat); | ||
const date = this.dateFormatTranslationService.parse(newDateValue, this.field.dateDisplayFormat, new Date()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you pass new date there as third param? what is the reason for that?
@@ -1,6 +1,6 @@ | |||
<div class="{{field.className}}" id="data-widget" [class.adf-invalid]="!field.isValid && isTouched()"> | |||
<mat-form-field class="adf-date-widget" [hideRequiredMarker]="true"> | |||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span class="adf-asterisk" | |||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }} ({{dateFormatTranslationService.convertDateFnsToMomentFormat(field.dateDisplayFormat)}})<span class="adf-asterisk" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please extract to a separate function so that template does not deal with services conversion directly:
formatLabel(field: FormField): string {
const displayName = this.translationService.instant(field.name);
const displayFormat = this.dateFormatTranslationService.convertDateFnsToMomentFormat(field.dateDisplayFormat);
return `${displayName} (${displayFormat})`;
}
then in HTML:
<label>{formatLabel(field)}</label>
also provide unit tests for the formatLabel function as it becomes easier
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implemented
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
imports: [TranslateModule.forRoot(), CoreTestingModule], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check if you need those imports, probably not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed unnecessary imports
import { CoreTestingModule } from '../testing/core.testing.module'; | ||
import { TranslateModule } from '@ngx-translate/core'; | ||
import { DatePipe } from './date.pipe'; | ||
import { DateFormatTranslationService } from '../form/public-api'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incorrect import path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -1,11 +1,11 @@ | |||
<div class="{{field.className}}" id="data-widget" [class.adf-invalid]="!field.isValid && isTouched()" [class.adf-left-label-input-container]="field.leftLabels"> | |||
<div *ngIf="field.leftLabels"> | |||
<label class="adf-label adf-left-label" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span class="adf-asterisk" | |||
<label class="adf-label adf-left-label" [attr.for]="field.id">{{field.name | translate }} ({{dateFormatTranslationService.convertDateFnsToMomentFormat(field.dateDisplayFormat)}})<span class="adf-asterisk" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs to be extracted to a function, UI templates should not deal with services directly, see https://github.com/Alfresco/alfresco-ng2-components/pull/8924/files#r1335592062
*ngIf="isRequired()">*</span></label> | ||
</div> | ||
<div> | ||
<mat-form-field class="adf-date-widget" [class.adf-left-label-input-datepicker]="field.leftLabels" [hideRequiredMarker]="true"> | ||
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span class="adf-asterisk" | ||
<label class="adf-label" *ngIf="!field.leftLabels" [attr.for]="field.id">{{field.name | translate }} ({{dateFormatTranslationService.convertDateFnsToMomentFormat(field.dateDisplayFormat)}})<span class="adf-asterisk" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs to be extracted to a function, UI templates should not deal with services directly, see https://github.com/Alfresco/alfresco-ng2-components/pull/8924/files#r1335592062
} | ||
} else { | ||
if (this.field.minValue) { | ||
this.minDate = moment(this.field.minValue, DATE_FORMAT_CLOUD); | ||
this.minDate = this.dateFormatTranslationService.format(new Date(this.field.minValue), DATE_FORMAT_CLOUD); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need translation if you already have new Date()
and export const DATE_FORMAT_CLOUD = 'yyyy-MM-dd';
? you can probably use datefns directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
after dome changes now, DATE_FORMAT_CLOUD is 'YYYY-MM-DD' like before.
It also helps to maintain uniformity across all places if we use format or parse methods from DateFnsUtils.
|
||
const momentDateAdapter = this.dateAdapter as MomentDateAdapter; | ||
momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat; | ||
this.dateFormatConfig.display.dateInput = this.field.dateDisplayFormat; | ||
|
||
if (this.field) { | ||
if (this.field.dynamicDateRangeSelection) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
review this block as you probably don't need format translation service as today
is a Date object
it('should return the input value when given an invalid date object', () => { | ||
const inputDate = new Date('invalid'); | ||
const dateFormat = 'DD-MM-YYYY'; | ||
const expectedOutput = inputDate.toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
your expected output should not be based on .toString() conversion, as whatever happens there the test will be just green. Add exact value it expects instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -583,3 +584,39 @@ export const FORM_FIELD_VALIDATORS = [ | |||
new MinDateTimeFieldValidator(), | |||
new MaxDateTimeFieldValidator() | |||
]; | |||
|
|||
export const momentToDateFnsMap = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are using this maps in 2 places, second is translation service; extract to a separate class and use same import in both cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved all logic to DateFnsUtils
a: 'A' | ||
}; | ||
|
||
export function convertMomentToDateFnsFormat(dateDisplayFormat: string): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
provide documentation comments for public functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added documentation
providedIn: 'root' | ||
}) | ||
export class DateFormatTranslationService { | ||
private momentToDateFnsMap = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are using this maps in 2 places, extract to a separate class and use same import in both cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you already have DateFnsUtils which can be a good place
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved all logic to DateFnsUtils
import { DatePipe } from './date.pipe'; | ||
import { DateFormatTranslationService } from '../form/public-api'; | ||
|
||
describe('DatePipe', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please provide tests with different variations of the date format, i.e.
- YYYY-MM-DD
- YYYY-DD-MM
- MM-DD-YY
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added steps to check wth different date formats
@@ -36,6 +36,7 @@ import { MomentDateTimePipe } from './moment-datetime.pipe'; | |||
import { FilterStringPipe } from './filter-string.pipe'; | |||
import { FilterOutArrayObjectsByPropPipe } from './filter-out-every-object-by-prop.pipe'; | |||
import { DateTimePipe } from './date-time.pipe'; | |||
import { DatePipe } from './date.pipe'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be AdfDatePipe not to clash with Angular DatePipe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed
return dateDisplayFormat; | ||
} | ||
|
||
export function convertDateFnsToMomentFormat(dateDisplayFormat: string): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move all these functions to DateFnsUtils
class to have a single place for all date/time code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved all logic to DateFnsUtils
return dateDisplayFormat; | ||
} | ||
|
||
export function formatUpdate(date: number|Date, dateFormat: string): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to DateFnsUtils class and use better naming, like formatDate
, it is already implied that some update is going to happen
return format(date, convertMomentToDateFnsFormat(dateFormat)); | ||
} | ||
|
||
export function parseUpdate(value: string, dateFormat: string, date = new Date()): Date { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to DateFnsUtils class and use better naming, like parseDate
, it is already implied that some update is going to happen
@Injectable({ | ||
providedIn: 'root' | ||
}) | ||
export class DateFormatTranslationService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This service has a lot of duplicated code with Field Validator funcitons.
you probably don't need this service at all, if you move all the field validator functions to DateFnsUtils, you can use those utils without this service
@@ -170,23 +171,23 @@ describe('DateWidgetComponent', () => { | |||
readOnly: 'false' | |||
}); | |||
widget.field.isVisible = true; | |||
widget.field.dateDisplayFormat = 'MM-DD-YYYY'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modified test data
|
||
fixture.detectChanges(); | ||
|
||
let dateElement: any = element.querySelector('#date-field-id'); | ||
expect(dateElement.value).toContain('12-30-9999'); | ||
|
||
widget.field.value = '5-6-2019 00:00'; | ||
widget.field.dateDisplayFormat = 'D-M-YYYY HH:mm'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is data coming from the backend
|
||
private onDestroy$ = new Subject<boolean>(); | ||
|
||
constructor(public formService: FormService, | ||
private dateAdapter: DateAdapter<Moment>, | ||
private userPreferencesService: UserPreferencesService) { | ||
private dateAdapter: DateAdapter<DateFnsAdapter>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incorrect parameter, should be the value type, not another adapter,
valid cases are DateAdapter<Moment | Date | string>
etc
cb8b9dd
to
27dbd03
Compare
SonarCloud Quality Gate failed. 0 Bugs No Coverage information Catch issues before they fail your Quality Gate with our IDE extension SonarLint |
closing as too many issues |
Please check if the PR fulfills these requirements
What kind of change does this PR introduce? (check one with "x")
What is the current behaviour? (You can also link to an open issue here)
Moment Library is being used in adfMomentDate Pipe.
What is the new behaviour?
This PR includes migration of 'lib/core/src/lib/pipes/moment-date.pipe.ts' into date-fns
Does this PR introduce a breaking change? (check one with "x")
If this PR contains a breaking change, please describe the impact and migration path for existing applications: ...
Other information:
https://alfresco.atlassian.net/browse/ACS-5857
There's one unit test case which needed the format of test data to be changed in order to validate it with the default format =>
https://github.com/Alfresco/alfresco-ng2-components/pull/8924/files#diff-b52520351ccf61f2557086298ce2a0d0e574463d39d0fa921085bcc2af1c1760R1116.
Rest all unit tests and e2es work fine without needing any changes.