From bd5473026abd004b414a7e5965f41a36f40ef398 Mon Sep 17 00:00:00 2001 From: fabianrios Date: Mon, 3 Jun 2024 11:08:38 +0200 Subject: [PATCH 1/2] introduce calendar weeks --- README.md | 1 + .../calendar-month-view.component.html | 9 ++++-- .../calendar-month-view.component.scss | 16 ++++++++++ .../calendar-month-view.component.ts | 29 +++++++++++++++++-- .../src/lib/date-time/calendar.component.html | 1 + .../src/lib/date-time/calendar.component.ts | 6 ++++ .../date-time-picker-container.component.html | 1 + .../src/lib/date-time/date-time.class.ts | 5 ++++ projects/picker/src/sass/picker.scss | 12 +++++++- 9 files changed, 75 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8c545f38..d9d46b16 100755 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ Properties for `owl-date-time` |`pickerMode`|`popup`, `dialog`|Optional|`popup`| The style the picker would open as. | |`startView`|`month`, `year`, `multi-year`|Optional|`month`| The view that the calendar should start in. | |`yearOnly`|boolean|Optional|`false`| Restricts the calendar to only show the year and multi-year views for month selection. | +|`showCalendarWeeks`|boolean|Optional|`false`| Whether to show calendar weeks in the calendar. | |`multiyearOnly`|boolean|Optional|`false`| Restricts the calendar to only show the multi-year view for year selection. | |`startAt`| T/null |Optional|`null`| The moment to open the picker to initially. | |`endAt`| T/null |Optional|`null`| The the default selected time for range calendar end time | diff --git a/projects/picker/src/lib/date-time/calendar-month-view.component.html b/projects/picker/src/lib/date-time/calendar-month-view.component.html index da441480..0f69a61c 100644 --- a/projects/picker/src/lib/date-time/calendar-month-view.component.html +++ b/projects/picker/src/lib/date-time/calendar-month-view.component.html @@ -1,4 +1,9 @@ - +
  • + {{ week }} +
  • + +
    @@ -9,7 +14,7 @@ - + * */ @Input() hideOtherMonths = false; + + /** + * Whether to show calendar weeks in the calendar + * */ + @Input() + showCalendarWeeks = false; private isDefaultFirstDayOfWeek = true; @@ -257,6 +263,11 @@ export class OwlMonthViewComponent * */ public todayDate: number | null; + /** + * Week day numbers + * */ + public weekNumbers: number[]; + /** * An array to hold all selectedDates' value * the value is the day number in current month @@ -485,6 +496,7 @@ export class OwlMonthViewComponent } this.todayDate = null; + this.weekNumbers = []; // the first weekday of the month const startWeekdayOfMonth = this.dateTimeAdapter.getDay( @@ -511,7 +523,6 @@ export class OwlMonthViewComponent daysDiff ); const dateCell = this.createDateCell(date, daysDiff); - // check if the date is today if ( this.dateTimeAdapter.isSameDay( @@ -526,11 +537,25 @@ export class OwlMonthViewComponent daysDiff += 1; } this._days.push(week); + if (this.showCalendarWeeks) { + const weekNumber = this.getISOWeek(new Date(week[0].ariaLabel)); + this.weekNumbers.push(weekNumber); + } } - this.setSelectedDates(); } + public getISOWeek(d: Date): number { + const clonedDate = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate())); + // Make Sunday's day number 7 + clonedDate.setUTCDate(clonedDate.getUTCDate() + 4 - (clonedDate.getUTCDay()||7)); + // Get first day of year + const yearStart = new Date(Date.UTC(clonedDate.getUTCFullYear(),0,1)); + // Calculate full weeks to nearest Thursday + const weekNo = Math.ceil(( ( (+clonedDate - +yearStart) / 86400000) + 1)/7); + return weekNo; + } + private updateFirstDayOfWeek(locale: string): void { if (this.isDefaultFirstDayOfWeek) { try { diff --git a/projects/picker/src/lib/date-time/calendar.component.html b/projects/picker/src/lib/date-time/calendar.component.html index b4c17c52..7b368fb0 100644 --- a/projects/picker/src/lib/date-time/calendar.component.html +++ b/projects/picker/src/lib/date-time/calendar.component.html @@ -70,6 +70,7 @@ [selecteds]="selecteds" [selectMode]="selectMode" [minDate]="minDate" + [showCalendarWeeks]="showCalendarWeeks" [maxDate]="maxDate" [dateFilter]="dateFilter" [hideOtherMonths]="hideOtherMonths" diff --git a/projects/picker/src/lib/date-time/calendar.component.ts b/projects/picker/src/lib/date-time/calendar.component.ts index 8d6dda39..01566492 100644 --- a/projects/picker/src/lib/date-time/calendar.component.ts +++ b/projects/picker/src/lib/date-time/calendar.component.ts @@ -236,6 +236,12 @@ export class OwlCalendarComponent */ @Input() yearOnly = false; + + /** + * Whether to show calendar weeks in the calendar + * */ + @Input() + showCalendarWeeks = false; /** * Whether to should only the multi-year view. diff --git a/projects/picker/src/lib/date-time/date-time-picker-container.component.html b/projects/picker/src/lib/date-time/date-time-picker-container.component.html index de7e4683..21b0c08f 100644 --- a/projects/picker/src/lib/date-time/date-time-picker-container.component.html +++ b/projects/picker/src/lib/date-time/date-time-picker-container.component.html @@ -15,6 +15,7 @@ [dateFilter]="picker.dateTimeFilter" [startView]="picker.startView" [yearOnly]="picker.yearOnly" + [showCalendarWeeks]="picker.showCalendarWeeks" [multiyearOnly]="picker.multiyearOnly" [hideOtherMonths]="picker.hideOtherMonths" (yearSelected)="picker.selectYear($event)" diff --git a/projects/picker/src/lib/date-time/date-time.class.ts b/projects/picker/src/lib/date-time/date-time.class.ts index cbafd24e..6c3a09e3 100644 --- a/projects/picker/src/lib/date-time/date-time.class.ts +++ b/projects/picker/src/lib/date-time/date-time.class.ts @@ -62,6 +62,11 @@ export abstract class OwlDateTime { @Input() startView: DateViewType = DateView.MONTH; + /** + * Whether to show calendar weeks in the calendar + * */ + @Input() + showCalendarWeeks = false; /** * Whether to should only the year and multi-year views. diff --git a/projects/picker/src/sass/picker.scss b/projects/picker/src/sass/picker.scss index daa7abb6..dabf928f 100644 --- a/projects/picker/src/sass/picker.scss +++ b/projects/picker/src/sass/picker.scss @@ -236,7 +236,7 @@ $theme-color: #3f51b5; } .owl-dt-calendar-view { - display: block; + display: flex; -webkit-box-flex: 1; flex: 1 1 auto; } @@ -287,6 +287,11 @@ $theme-color: #3f51b5; height: 1px; background: rgba(0, 0, 0, .12); } + &.owl-calendar-weeks { + &:after { + left: -1.8em; + } + } } } @@ -374,6 +379,11 @@ $theme-color: #3f51b5; border-bottom-right-radius: 999px; } } + &.owl-calendar-weeks { + .owl-dt-calendar-cell-content { + height: 86%; // adjust for the additional space taked for calendar weeks + } + } } .owl-dt-timer { From 78753f3cf6cd75871eaf290137e79ccc5c4da4d3 Mon Sep 17 00:00:00 2001 From: fabianrios Date: Mon, 15 Jul 2024 17:40:49 +0200 Subject: [PATCH 2/2] includeCalendarWeeks add test for calendar week feature --- .../lib/date-time/calendar.component.spec.ts | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/projects/picker/src/lib/date-time/calendar.component.spec.ts b/projects/picker/src/lib/date-time/calendar.component.spec.ts index cd29a3ac..61c5c1ea 100644 --- a/projects/picker/src/lib/date-time/calendar.component.spec.ts +++ b/projects/picker/src/lib/date-time/calendar.component.spec.ts @@ -46,6 +46,7 @@ describe('OwlCalendarComponent', () => { imports: [OwlNativeDateTimeModule, OwlDateTimeModule], declarations: [ StandardCalendarComponent, + CalendarWithCalendarWeeks, CalendarWithMinMaxComponent, CalendarWithDateFilterComponent ], @@ -294,6 +295,60 @@ describe('OwlCalendarComponent', () => { }); }); + describe('calendar with Calendar Weeks', () => { + let fixture: ComponentFixture; + let testComponent: CalendarWithCalendarWeeks; + let calendarElement: HTMLElement; + let calendarInstance: OwlCalendarComponent; + + beforeEach(() => { + fixture = TestBed.createComponent(CalendarWithCalendarWeeks); + fixture.detectChanges(); + + const calendarDebugElement = fixture.debugElement.query( + By.directive(OwlCalendarComponent) + ); + calendarElement = calendarDebugElement.nativeElement; + + calendarInstance = calendarDebugElement.componentInstance; + testComponent = fixture.componentInstance; + }); + + it('should show calendar weeks when attribute showCalendarWeeks in true', () => { + // Check the initial value is false + expect(calendarInstance.showCalendarWeeks).toBe(false); + testComponent.showCalendarWeeks = true; + fixture.detectChanges(); // Trigger change detection to apply the new value + // Now check if the calendarInstance reflects this change + expect(calendarInstance.showCalendarWeeks).toBe(true); + }); + + it('should show calendar weeks classes only when attribute showCalendarWeeks in true', () => { + // Check the initial value is false + expect(calendarInstance.showCalendarWeeks).toBe(false); + + // Verify classes are not present initially + let weekNumberElement = fixture.debugElement.nativeElement.querySelector('.week-number'); + let owlCalendarWeeksElement = fixture.debugElement.nativeElement.querySelector('.owl-calendar-weeks'); + expect(weekNumberElement).toBeNull(); + expect(owlCalendarWeeksElement).toBeNull(); + + // Set showCalendarWeeks to true + testComponent.showCalendarWeeks = true; + fixture.detectChanges(); // Trigger change detection to apply the new value + + // Now check if the calendarInstance reflects this change + expect(calendarInstance.showCalendarWeeks).toBe(true); + + // Verify classes are present after the change + weekNumberElement = fixture.debugElement.nativeElement.querySelector('.week-number'); + owlCalendarWeeksElement = fixture.debugElement.nativeElement.querySelector('.owl-calendar-weeks'); + expect(weekNumberElement).toBeTruthy(); + expect(owlCalendarWeeksElement).toBeTruthy(); + }); + }); + + describe('calendar with min and max', () => { let fixture: ComponentFixture; let testComponent: CalendarWithMinMaxComponent; @@ -502,6 +557,20 @@ class CalendarWithMinMaxComponent { pickerMoment = new Date(2018, JAN, 31); } +@Component({ + template: ` + + ` +}) +class CalendarWithCalendarWeeks { + selectMode = 'single'; + startAt: Date; + showCalendarWeeks = false; + pickerMoment = new Date(2018, JAN, 31); +} + @Component({ template: `