Skip to content

Commit

Permalink
Merge pull request #110 from europeana/feat/MET-4039-Material-Datepic…
Browse files Browse the repository at this point in the history
…ker-And-Format

MET-4039 Use Material Range Picker / un-GB locale / custom formatter …
  • Loading branch information
andyjmaclean committed Dec 21, 2021
2 parents 101ad80 + 7ba6e16 commit 7c0b7b0
Show file tree
Hide file tree
Showing 19 changed files with 279 additions and 127 deletions.
10 changes: 8 additions & 2 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
"pdfmake"
],
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
],
"scripts": [],
"vendorChunk": true,
"extractLicenses": false,
Expand Down Expand Up @@ -107,7 +110,10 @@
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
],
"scripts": [],
"codeCoverageExclude": ["src/app/_mocked/*.ts"]
}
Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/filters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ context('statistics-dashboard', () => {
cy.get(selDateTo).type(today);

cy.get(selCloseDateOverride).should('be.visible');
cy.get(selDateFrom).clear();
cy.get(selDateFrom).clear(force);
cy.get(selCloseDateOverride).should('not.be.visible');
});

Expand Down
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@angular/compiler": "^12.2.7",
"@angular/core": "~12.2.7",
"@angular/forms": "~12.2.7",
"@angular/material": "^11.2.13",
"@angular/platform-browser": "~12.2.7",
"@angular/platform-browser-dynamic": "~12.2.7",
"@angular/router": "~12.2.7",
Expand Down
3 changes: 2 additions & 1 deletion src/app/_data/static-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,8 @@ export const RightsStatements = {
'//creativecommons.org/licenses/by-nc-sa/3.0/lu': 'CC BY-NC-SA 3.0 LU',
'//creativecommons.org/licenses/by-nc-sa/3.0/pl': 'CC BY-NC-SA 3.0 PL',
'//creativecommons.org/licenses/by-nc-sa/4.0': 'CC BY-NC-SA 4.0',
'//creativecommons.org/licenses/by-nc-sa/4.0/deed.de': 'CC BY-NC-SA 4.0 (deed.de)',
'//creativecommons.org/licenses/by-nc-sa/4.0/deed.de':
'CC BY-NC-SA 4.0 (deed.de)',

'//creativecommons.org/licenses/by-nd/2.0/es': 'CC BY-ND 2.0 ES',
'//creativecommons.org/licenses/by-nd/2.5/pl': 'CC BY-ND 2.5 PL',
Expand Down
28 changes: 25 additions & 3 deletions src/app/_directives/click-aware/click-aware.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ClickAwareDirective } from '.';
<br />
<br />
<br />
<span class="dead-inner-element">CHILD</span>
</div>
<div
class="live-zone"
Expand Down Expand Up @@ -63,9 +64,6 @@ describe('ClickAwareDirective', () => {

it('should call the "documentClickListener" method when clicked', () => {
const onClickMock = spyOn(component, 'clicked').and.callThrough();
fixture.debugElement
.query(By.css('.dead-zone'))
.triggerEventHandler('click', null);

deadElement.nativeElement.click();
expect(onClickMock).not.toHaveBeenCalled();
Expand All @@ -92,6 +90,30 @@ describe('ClickAwareDirective', () => {
expect(clickInfo.isClickedInside).toBeTruthy();
});

it('should detect clicks in the "includeClicksOnClass" element', () => {
const clickInfo = component.clickInfo;

expect(clickInfo.isClickedInside).toBeFalsy();

const deadElementInner = fixture.debugElement.query(
By.css('.dead-zone .dead-inner-element')
);

clickInfo.documentClickListener(
liveElement.nativeElement,
deadElementInner.nativeElement
);
expect(clickInfo.isClickedInside).toBeFalsy();

clickInfo.includeClicksOnClass = 'cmp';

clickInfo.documentClickListener(
liveElement.nativeElement,
deadElementInner.nativeElement
);
expect(clickInfo.isClickedInside).toBeTruthy();
});

it('should detect clicks in the element via the service', () => {
const clickInfo = component.clickInfo;
const cmpClickService =
Expand Down
25 changes: 24 additions & 1 deletion src/app/_directives/click-aware/click-aware.directive.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Directive, ElementRef, EventEmitter, Output } from '@angular/core';
import {
Directive,
ElementRef,
EventEmitter,
Input,
Output
} from '@angular/core';
import { SubscriptionManager } from '../../subscription-manager';
import { ClickService } from '../../_services';

Expand All @@ -8,6 +14,7 @@ import { ClickService } from '../../_services';
})
export class ClickAwareDirective extends SubscriptionManager {
@Output() clickOutside: EventEmitter<void> = new EventEmitter();
@Input() includeClicksOnClass: string;

isClickedInside = false;

Expand Down Expand Up @@ -39,6 +46,22 @@ export class ClickAwareDirective extends SubscriptionManager {
clickTarget: HTMLElement
): void {
this.isClickedInside = nativeElement.contains(clickTarget);

if (!this.isClickedInside && this.includeClicksOnClass) {
let node = clickTarget.parentNode;
while (node) {
const classList = (node as any as HTMLElement).classList;
if (classList) {
classList.forEach((className: string) => {
if (className === this.includeClicksOnClass) {
this.isClickedInside = true;
}
});
}
node = node.parentNode as any as HTMLElement;
}
}

if (!this.isClickedInside) {
this.clickOutside.emit();
}
Expand Down
43 changes: 32 additions & 11 deletions src/app/_helpers/date-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
import { FormControl } from '@angular/forms';

export const today = new Date().toISOString().split('T')[0];

export const yearZero = new Date(Date.parse('20 Nov 2008 12:00:00 GMT'))
.toISOString()
.split('T')[0];

/** dateToUCT
/* @param {Date} localDate
/* @returns creates a UCT date from a local date, adjusted by the local date's offset
*/
export function dateToUCT(localDate: Date): Date {
const dateUTC = new Date(localDate.toISOString());
return new Date(dateUTC.getTime() - localDate.getTimezoneOffset() * 60000);
}

/** getDateAsISOString
/* @param {Date} localDate
/* - returns 'yyyy-mm-dd'
*/
export function getDateAsISOString(localDate: Date): string {
return dateToUCT(localDate).toISOString().split('T')[0];
}

/** validateDateGeneric
/* @param {FormControl} control - the field to validate
/* @param {string} fieldName - the field name
Expand All @@ -19,21 +37,24 @@ export function validateDateGeneric(
let isTooLate = false;
if (val) {
const otherField = fieldName === 'dateFrom' ? 'dateTo' : 'dateFrom';
const dateVal = new Date(val);
const dateVal = dateToUCT(new Date(val));

if (dateVal < new Date(yearZero)) {
console.log('less than year zero(' + yearZero + '): ' + dateVal);
isTooEarly = true;
} else if (dateVal > new Date(today)) {
} else if (dateVal > dateToUCT(new Date(today))) {
isTooLate = true;
} else if (control.parent.value[otherField].length > 0) {
const dateOtherVal = new Date(control.parent.value[otherField]);
if (otherField === 'dateFrom') {
if (dateVal < dateOtherVal) {
console.log('less than year otjer(' + dateOtherVal + '): ' + dateVal);
isTooEarly = true;
} else {
const otherValue = control.parent.value[otherField];
if (otherValue && otherValue.length > 0) {
const dateOtherVal = new Date(otherValue);

if (otherField === 'dateFrom') {
if (dateVal < new Date(otherValue)) {
isTooEarly = true;
}
} else if (dateVal > dateToUCT(new Date(otherValue))) {
isTooLate = true;
}
} else if (dateVal > dateOtherVal) {
isTooLate = true;
}
}
}
Expand Down
55 changes: 53 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatDatepickerModule } from '@angular/material/datepicker';
import {
DateAdapter,
MatNativeDateModule,
MAT_DATE_FORMATS,
MAT_DATE_LOCALE,
NativeDateAdapter
} from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { ClickAwareDirective, IsScrollableDirective } from './_directives';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
Expand All @@ -30,6 +38,28 @@ import { ResizeComponent } from './resize';
import { SnapshotsComponent } from './snapshots';
import { TruncateComponent } from './truncate';

import { getDateAsISOString } from './_helpers';

class AppDateAdapter extends NativeDateAdapter {
format(date: Date, displayFormat: Object): string {
if (displayFormat === 'input' || displayFormat === 'DD/MM/YYYY') {
return getDateAsISOString(date).split('-').reverse().join('/');
}
return date.toDateString();
}

parse(value: any): Date | null {
if (typeof value === 'string' && value.indexOf('/') > -1) {
const str = value.split('/');
const year = Number(str[2]);
const month = Number(str[1]) - 1;
const date = Number(str[0]);
return new Date(year, month, date);
}
return null;
}
}

@NgModule({
declarations: [
AppComponent,
Expand Down Expand Up @@ -63,9 +93,30 @@ import { TruncateComponent } from './truncate';
CommonModule,
FormsModule,
HttpClientModule,
MatDatepickerModule,
MatFormFieldModule,
MatNativeDateModule,
ReactiveFormsModule
],
providers: [],
providers: [
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
{ provide: DateAdapter, useClass: AppDateAdapter },
{
provide: MAT_DATE_FORMATS,
useValue: {
parse: {
dateInput: 'DD/MM/YYYY'
},
dateInput: 'DD/MM/YYYY',
display: {
dateInput: 'DD/MM/YYYY',
monthYearLabel: 'MM YYYY',
dateA11yLabel: 'MM',
monthYearA11yLabel: 'MMMM YYYY'
}
}
}
],
bootstrap: [AppComponent]
})
export class AppModule {}
Loading

0 comments on commit 7c0b7b0

Please sign in to comment.