Skip to content

Commit e296357

Browse files
etwillbefineMatt Lewis
authored and
Matt Lewis
committed
feat(excludeDays): add an option to hide days on the month and week views
1 parent 3d3eb88 commit e296357

13 files changed

+233
-19
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
node_modules
44
typings
55
coverage
6+
dist

demos/demo-app.module.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import * as disableTooltips from './demo-modules/disable-tooltips';
3434
import * as additionalEventProperties from './demo-modules/additional-event-properties';
3535
import * as selectableMonthDay from './demo-modules/selectable-month-day';
3636
import * as minMaxDate from './demo-modules/min-max-date';
37+
import * as excludeDays from './demo-modules/exclude-days';
3738

3839
@NgModule({
3940
declarations: [DemoAppComponent],
@@ -64,6 +65,7 @@ import * as minMaxDate from './demo-modules/min-max-date';
6465
additionalEventProperties.DemoModule,
6566
selectableMonthDay.DemoModule,
6667
minMaxDate.DemoModule,
68+
excludeDays.DemoModule,
6769
RouterModule.forRoot([{
6870
path: 'kitchen-sink',
6971
component: kitchenSink.DemoComponent,
@@ -154,6 +156,12 @@ import * as minMaxDate from './demo-modules/min-max-date';
154156
data: {
155157
label: 'Day modifier'
156158
}
159+
}, {
160+
path: 'exclude-days',
161+
component: excludeDays.DemoComponent,
162+
data: {
163+
label: 'Exclude Weekends'
164+
}
157165
}, {
158166
path: 'i18n',
159167
component: i18n.DemoComponent,
@@ -217,4 +225,4 @@ import * as minMaxDate from './demo-modules/min-max-date';
217225
],
218226
bootstrap: [DemoAppComponent]
219227
})
220-
export class DemoAppModule {}
228+
export class DemoAppModule {}

demos/demo-modules/day-modifier/template.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020
[viewDate]="viewDate"
2121
[events]="events">
2222
</mwl-calendar-day-view>
23-
</div>
23+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
2+
import { CalendarEvent } from 'angular-calendar';
3+
import { subDays, addDays } from 'date-fns';
4+
import { colors } from '../demo-utils/colors';
5+
6+
@Component({
7+
selector: 'mwl-demo-component',
8+
changeDetection: ChangeDetectionStrategy.OnPush,
9+
encapsulation: ViewEncapsulation.None,
10+
templateUrl: 'template.html',
11+
})
12+
export class DemoComponent {
13+
14+
view: string = 'month';
15+
16+
viewDate: Date = new Date('2016-01-05');
17+
18+
events: CalendarEvent[] = [{
19+
start: new Date('2016-01-08'),
20+
end: new Date('2016-01-10'),
21+
title: 'One day excluded event',
22+
color: colors.red
23+
}, {
24+
start: new Date('2016-01-01'),
25+
end: new Date('2016-01-09'),
26+
title: 'Multiple weeks event',
27+
color: colors.blue
28+
}];
29+
30+
// exclude weekends
31+
excludeDays: number[] = [0, 6];
32+
33+
skipWeekends(direction: 'back' | 'forward'): void {
34+
if (this.view === 'day') {
35+
if (direction === 'back') {
36+
while (this.excludeDays.indexOf(this.viewDate.getDay()) > -1) {
37+
this.viewDate = subDays(this.viewDate, 1);
38+
}
39+
} else if (direction === 'forward') {
40+
while (this.excludeDays.indexOf(this.viewDate.getDay()) > -1) {
41+
this.viewDate = addDays(this.viewDate, 1);
42+
}
43+
}
44+
}
45+
}
46+
47+
}
48+
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './module';
2+
export * from './component';
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { NgModule } from '@angular/core';
2+
import { CommonModule } from '@angular/common';
3+
import { CalendarModule } from 'angular-calendar';
4+
import { DemoUtilsModule } from '../demo-utils/module';
5+
import { DemoComponent } from './component';
6+
7+
@NgModule({
8+
imports: [
9+
CommonModule,
10+
CalendarModule.forRoot(),
11+
DemoUtilsModule
12+
],
13+
declarations: [
14+
DemoComponent
15+
],
16+
exports: [
17+
DemoComponent
18+
]
19+
})
20+
export class DemoModule {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<div class="row text-center">
2+
<div class="col-md-4">
3+
<div class="btn-group">
4+
<div
5+
class="btn btn-primary"
6+
mwlCalendarPreviousView
7+
[view]="view"
8+
[(viewDate)]="viewDate"
9+
(viewDateChange)="skipWeekends('back')">
10+
Previous
11+
</div>
12+
<div
13+
class="btn btn-secondary"
14+
mwlCalendarToday
15+
[(viewDate)]="viewDate">
16+
Today
17+
</div>
18+
<div
19+
class="btn btn-primary"
20+
mwlCalendarNextView
21+
[view]="view"
22+
[(viewDate)]="viewDate"
23+
(viewDateChange)="skipWeekends('forward')">
24+
Next
25+
</div>
26+
</div>
27+
</div>
28+
<div class="col-md-4">
29+
<h3>{{ viewDate | calendarDate:(view + 'ViewTitle'):'en' }}</h3>
30+
</div>
31+
<div class="col-md-4">
32+
<div class="btn-group">
33+
<div
34+
class="btn btn-primary"
35+
(click)="view = 'month'"
36+
[class.active]="view === 'month'">
37+
Month
38+
</div>
39+
<div
40+
class="btn btn-primary"
41+
(click)="view = 'week'"
42+
[class.active]="view === 'week'">
43+
Week
44+
</div>
45+
<div
46+
class="btn btn-primary"
47+
(click)="view = 'day'"
48+
[class.active]="view === 'day'">
49+
Day
50+
</div>
51+
</div>
52+
</div>
53+
</div>
54+
<br>
55+
56+
<div [ngSwitch]="view">
57+
<mwl-calendar-month-view
58+
*ngSwitchCase="'month'"
59+
[viewDate]="viewDate"
60+
[events]="events"
61+
[excludeDays]="excludeDays">
62+
</mwl-calendar-month-view>
63+
<mwl-calendar-week-view
64+
*ngSwitchCase="'week'"
65+
[excludeDays]="excludeDays"
66+
[viewDate]="viewDate"
67+
[events]="events">
68+
</mwl-calendar-week-view>
69+
<mwl-calendar-day-view
70+
*ngSwitchCase="'day'"
71+
[viewDate]="viewDate"
72+
[events]="events">
73+
</mwl-calendar-day-view>
74+
</div>

demos/demo-modules/selectable-month-day/component.ts

-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,3 @@ export class DemoComponent {
3131
}
3232

3333
}
34-

demos/demo-modules/selectable-month-day/template.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
[viewDate]="viewDate"
33
[events]="events"
44
(dayClicked)="dayClicked($event.day)">
5-
</mwl-calendar-month-view>
5+
</mwl-calendar-month-view>

src/components/month/calendarMonthView.component.ts

+14-8
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ import { CalendarEventTimesChangedEvent } from '../../interfaces/calendarEventTi
6060
<div *ngFor="let rowIndex of view.rowOffsets">
6161
<div class="cal-cell-row">
6262
<mwl-calendar-month-cell
63-
*ngFor="let day of view.days | slice : rowIndex : rowIndex + 7"
63+
*ngFor="let day of view.days | slice : rowIndex : rowIndex + (view.totalDaysVisibleInWeek)"
6464
[class.cal-drag-over]="day.dragOver"
6565
[day]="day"
6666
[openDay]="openDay"
@@ -98,6 +98,11 @@ export class CalendarMonthViewComponent implements OnChanges, OnInit, OnDestroy
9898
*/
9999
@Input() events: CalendarEvent[] = [];
100100

101+
/**
102+
* An array of day indexes (0 = sunday, 1 = monday etc) that will be hidden on the view
103+
*/
104+
@Input() excludeDays: number[] = [];
105+
101106
/**
102107
* Whether the events list for the day of the `viewDate` option is visible or not
103108
*/
@@ -193,18 +198,17 @@ export class CalendarMonthViewComponent implements OnChanges, OnInit, OnDestroy
193198
*/
194199
ngOnChanges(changes: any): void {
195200

196-
if (changes.viewDate) {
201+
if (changes.viewDate || changes.excludeDays) {
197202
this.refreshHeader();
198203
}
199204

200-
if (changes.viewDate || changes.events) {
205+
if (changes.viewDate || changes.events || changes.excludeDays) {
201206
this.refreshBody();
202207
}
203208

204-
if (changes.activeDayIsOpen || changes.viewDate || changes.events) {
209+
if (changes.activeDayIsOpen || changes.viewDate || changes.events || changes.excludeDays) {
205210
this.checkActiveDayIsOpen();
206211
}
207-
208212
}
209213

210214
/**
@@ -248,15 +252,17 @@ export class CalendarMonthViewComponent implements OnChanges, OnInit, OnDestroy
248252
private refreshHeader(): void {
249253
this.columnHeaders = getWeekViewHeader({
250254
viewDate: this.viewDate,
251-
weekStartsOn: this.weekStartsOn
255+
weekStartsOn: this.weekStartsOn,
256+
excluded: this.excludeDays
252257
});
253258
}
254259

255260
private refreshBody(): void {
256261
this.view = getMonthView({
257262
events: this.events,
258263
viewDate: this.viewDate,
259-
weekStartsOn: this.weekStartsOn
264+
weekStartsOn: this.weekStartsOn,
265+
excluded: this.excludeDays
260266
});
261267
if (this.dayModifier) {
262268
this.view.days.forEach(day => this.dayModifier(day));
@@ -267,7 +273,7 @@ export class CalendarMonthViewComponent implements OnChanges, OnInit, OnDestroy
267273
if (this.activeDayIsOpen === true) {
268274
this.openDay = this.view.days.find(day => isSameDay(day.date, this.viewDate));
269275
const index: number = this.view.days.indexOf(this.openDay);
270-
this.openRowIndex = Math.floor(index / 7) * 7;
276+
this.openRowIndex = Math.floor(index / this.view.totalDaysVisibleInWeek) * this.view.totalDaysVisibleInWeek;
271277
} else {
272278
this.openRowIndex = null;
273279
this.openDay = null;

src/components/week/calendarWeekView.component.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ import { CalendarEventTimesChangedEvent } from '../../interfaces/calendarEventTi
5959
#event
6060
[class.cal-draggable]="weekEvent.event.draggable"
6161
*ngFor="let weekEvent of eventRow.row"
62-
[style.width]="((100 / 7) * weekEvent.span) + '%'"
63-
[style.marginLeft]="((100 / 7) * weekEvent.offset) + '%'"
62+
[style.width]="((100 / days.length) * weekEvent.span) + '%'"
63+
[style.marginLeft]="((100 / days.length) * weekEvent.offset) + '%'"
6464
mwlResizable
6565
[resizeEdges]="{left: weekEvent.event?.resizable?.beforeStart, right: weekEvent.event?.resizable?.afterEnd}"
6666
[resizeSnapGrid]="{left: getDayColumnWidth(eventRowContainer), right: getDayColumnWidth(eventRowContainer)}"
@@ -96,6 +96,11 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
9696
*/
9797
@Input() events: CalendarEvent[] = [];
9898

99+
/**
100+
* An array of day indexes (0 = sunday, 1 = monday etc) that will be hidden on the view
101+
*/
102+
@Input() excludeDays: number[] = [];
103+
99104
/**
100105
* An observable that when emitted on will re-render the current view
101106
*/
@@ -189,11 +194,11 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
189194
*/
190195
ngOnChanges(changes: any): void {
191196

192-
if (changes.viewDate) {
197+
if (changes.viewDate || changes.excludeDays) {
193198
this.refreshHeader();
194199
}
195200

196-
if (changes.events || changes.viewDate) {
201+
if (changes.events || changes.viewDate || changes.excludeDays) {
197202
this.refreshBody();
198203
}
199204

@@ -284,7 +289,7 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
284289
* @hidden
285290
*/
286291
getDayColumnWidth(eventRowContainer: HTMLElement): number {
287-
return Math.floor(eventRowContainer.offsetWidth / 7);
292+
return Math.floor(eventRowContainer.offsetWidth / this.days.length);
288293
}
289294

290295
/**
@@ -299,15 +304,17 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
299304
private refreshHeader(): void {
300305
this.days = getWeekViewHeader({
301306
viewDate: this.viewDate,
302-
weekStartsOn: this.weekStartsOn
307+
weekStartsOn: this.weekStartsOn,
308+
excluded: this.excludeDays
303309
});
304310
}
305311

306312
private refreshBody(): void {
307313
this.eventRows = getWeekView({
308314
events: this.events,
309315
viewDate: this.viewDate,
310-
weekStartsOn: this.weekStartsOn
316+
weekStartsOn: this.weekStartsOn,
317+
excluded: this.excludeDays
311318
});
312319
}
313320

test/calendarMonthView.component.spec.ts

+23
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,33 @@ describe('calendarMonthView component', () => {
4545
fixture.componentInstance.ngOnChanges({viewDate: {}});
4646
expect(fixture.componentInstance.view.rowOffsets).to.deep.equal([0, 7, 14, 21, 28]);
4747
expect(fixture.componentInstance.view.days.length).to.equal(35);
48+
expect(fixture.componentInstance.view.totalDaysVisibleInWeek).to.equal(7);
4849
expect(fixture.componentInstance.view.days[0].date).to.deep.equal(moment('2016-05-29').toDate());
4950
fixture.destroy();
5051
});
5152

53+
it('should generate the month view without from week excluded days', () => {
54+
const fixture: ComponentFixture<CalendarMonthViewComponent> = TestBed.createComponent(CalendarMonthViewComponent);
55+
fixture.componentInstance.viewDate = new Date('2016-01-10');
56+
fixture.componentInstance.excludeDays = [0, 6];
57+
fixture.componentInstance.ngOnChanges({viewDate: {}});
58+
expect(fixture.componentInstance.view.days.length).to.equal(30);
59+
expect(fixture.componentInstance.view.totalDaysVisibleInWeek).to.equal(5);
60+
expect(fixture.componentInstance.view.rowOffsets).to.deep.equal([0, 5, 10, 15, 20, 25]);
61+
expect(fixture.componentInstance.view.days[0].date).to.deep.equal(moment('2015-12-28').toDate());
62+
fixture.destroy();
63+
});
64+
65+
it('should update the month view when excluded days changed', () => {
66+
const fixture: ComponentFixture<CalendarMonthViewComponent> = TestBed.createComponent(CalendarMonthViewComponent);
67+
fixture.componentInstance.viewDate = new Date('2016-01-10');
68+
fixture.componentInstance.excludeDays = [0, 1, 2];
69+
fixture.componentInstance.ngOnChanges({excludeDays: {}});
70+
expect(fixture.componentInstance.view.days.length).to.equal(24);
71+
expect(fixture.componentInstance.view.totalDaysVisibleInWeek).to.equal(4);
72+
fixture.destroy();
73+
});
74+
5275
it('should open and close the active day events list', () => {
5376
const fixture: ComponentFixture<CalendarMonthViewComponent> = TestBed.createComponent(CalendarMonthViewComponent);
5477
expect(fixture.componentInstance.openRowIndex).to.be.undefined;

0 commit comments

Comments
 (0)