Skip to content

Commit 84a9e59

Browse files
committed
Converted UI to agenda-based UI
1 parent 18c07d6 commit 84a9e59

6 files changed

Lines changed: 242 additions & 62 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
.calendar-view-date-cell {
2+
width: 150px;
3+
}
4+
5+
.calendar-view-date {
6+
width: 40px;
7+
font-size: 36px;
8+
line-height: 36px;
9+
margin-right: 10px;
10+
}
11+
12+
.calendar-view-month {
13+
font-size: 0.75em;
14+
}
15+
16+
.calendar-view-timespan {
17+
width: 200px;
18+
}
19+
20+
.calendar-view-subject {
21+
font-size: 1.25em;
22+
}
23+
24+
.calendar-view-organizer {
25+
font-size: .75em;
26+
}

demo/graph-tutorial/src/Calendar.tsx

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,28 @@
22
// Licensed under the MIT License.
33
import React from 'react';
44
import { Table } from 'reactstrap';
5-
import moment from 'moment-timezone';
5+
import moment, { Moment } from 'moment-timezone';
66
import { findOneIana } from "windows-iana";
77
import { Event } from 'microsoft-graph';
88
import { config } from './Config';
99
import { getUserWeekCalendar } from './GraphService';
1010
import withAuthProvider, { AuthComponentProps } from './AuthProvider';
11+
import CalendarDayRow from './CalendarDayRow';
12+
import './Calendar.css';
1113

1214
interface CalendarState {
1315
eventsLoaded: boolean;
1416
events: Event[];
15-
}
16-
17-
export interface CalendarProps extends AuthComponentProps {
18-
timeZone: any;
19-
timeFormat: any;
20-
}
21-
22-
// Helper function to format Graph date/time
23-
function formatDateTime(dateTime: string | undefined) {
24-
if (dateTime !== undefined) {
25-
return moment(dateTime).format('M/D/YY h:mm A');
26-
}
17+
startOfWeek: Moment | undefined;
2718
}
2819

2920
class Calendar extends React.Component<AuthComponentProps, CalendarState> {
3021
constructor(props: any) {
3122
super(props);
32-
console.log('Constructor: ' + JSON.stringify(props.user));
3323
this.state = {
3424
eventsLoaded: false,
35-
events: []
25+
events: [],
26+
startOfWeek: undefined
3627
};
3728
}
3829

@@ -53,11 +44,16 @@ class Calendar extends React.Component<AuthComponentProps, CalendarState> {
5344
// but in UTC. For example, for Pacific Standard Time, the time value would be
5445
// 07:00:00Z
5546
var startOfWeek = moment.tz(ianaTimeZone!.valueOf()).startOf('week').utc();
56-
console.log(`Start of week: ${startOfWeek}`);
47+
5748
// Get the user's events
5849
var events = await getUserWeekCalendar(accessToken, this.props.user.timeZone, startOfWeek);
50+
5951
// Update the array of events in state
60-
this.setState({ eventsLoaded: true, events: events.value });
52+
this.setState({
53+
eventsLoaded: true,
54+
events: events,
55+
startOfWeek: startOfWeek
56+
});
6157
}
6258
catch (err) {
6359
this.props.setError('ERROR', JSON.stringify(err));
@@ -67,32 +63,63 @@ class Calendar extends React.Component<AuthComponentProps, CalendarState> {
6763

6864
// <renderSnippet>
6965
render() {
66+
var sunday = moment(this.state.startOfWeek);
67+
var monday = moment(sunday).add(1, 'day');
68+
var tuesday = moment(monday).add(1, 'day');
69+
var wednesday = moment(tuesday).add(1, 'day');
70+
var thursday = moment(wednesday).add(1, 'day');
71+
var friday = moment(thursday).add(1, 'day');
72+
var saturday = moment(friday).add(1, 'day');
73+
7074
return (
7175
<div>
72-
<h1>Calendar</h1>
73-
<Table>
74-
<thead>
75-
<tr>
76-
<th scope="col">Organizer</th>
77-
<th scope="col">Subject</th>
78-
<th scope="col">Start</th>
79-
<th scope="col">End</th>
80-
</tr>
81-
</thead>
82-
<tbody>
83-
{this.state.events.map(
84-
function(event: Event){
85-
return(
86-
<tr key={event.id}>
87-
<td>{event.organizer?.emailAddress?.name}</td>
88-
<td>{event.subject}</td>
89-
<td>{formatDateTime(event.start?.dateTime)}</td>
90-
<td>{formatDateTime(event.end?.dateTime)}</td>
91-
</tr>
92-
);
93-
})}
94-
</tbody>
95-
</Table>
76+
<div className="mb-3">
77+
<h1 className="mb-3">{sunday.format('MMMM D, YYYY')} - {saturday.format('MMMM D, YYYY')}</h1>
78+
<a className="btn btn-light btn-sm" href="#">New event</a>
79+
</div>
80+
<div className="calendar-week">
81+
<div className="table-responsive">
82+
<Table size="sm">
83+
<thead>
84+
<tr>
85+
<th>Date</th>
86+
<th>Time</th>
87+
<th>Event</th>
88+
</tr>
89+
</thead>
90+
<tbody>
91+
<CalendarDayRow
92+
date={sunday}
93+
timeFormat={this.props.user.timeFormat}
94+
events={this.state.events.filter(event => moment(event.start?.dateTime).day() === sunday.day()) } />
95+
<CalendarDayRow
96+
date={monday}
97+
timeFormat={this.props.user.timeFormat}
98+
events={this.state.events.filter(event => moment(event.start?.dateTime).day() === monday.day()) } />
99+
<CalendarDayRow
100+
date={tuesday}
101+
timeFormat={this.props.user.timeFormat}
102+
events={this.state.events.filter(event => moment(event.start?.dateTime).day() === tuesday.day()) } />
103+
<CalendarDayRow
104+
date={wednesday}
105+
timeFormat={this.props.user.timeFormat}
106+
events={this.state.events.filter(event => moment(event.start?.dateTime).day() === wednesday.day()) } />
107+
<CalendarDayRow
108+
date={thursday}
109+
timeFormat={this.props.user.timeFormat}
110+
events={this.state.events.filter(event => moment(event.start?.dateTime).day() === thursday.day()) } />
111+
<CalendarDayRow
112+
date={friday}
113+
timeFormat={this.props.user.timeFormat}
114+
events={this.state.events.filter(event => moment(event.start?.dateTime).day() === friday.day()) } />
115+
<CalendarDayRow
116+
date={saturday}
117+
timeFormat={this.props.user.timeFormat}
118+
events={this.state.events.filter(event => moment(event.start?.dateTime).day() === saturday.day()) } />
119+
</tbody>
120+
</Table>
121+
</div>
122+
</div>
96123
</div>
97124
);
98125
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
// <CalendarDayRowSnippet>
5+
import React from 'react';
6+
import moment, { Moment } from 'moment';
7+
import { Event } from 'microsoft-graph';
8+
9+
interface CalendarDayRowProps {
10+
date: Moment | undefined;
11+
timeFormat: string;
12+
events: Event[];
13+
}
14+
15+
interface FormatMap {
16+
[key: string] : string;
17+
}
18+
19+
// moment.js format strings are slightly
20+
// different than the ones returned by Graph
21+
const formatMap: FormatMap = {
22+
"h:mm tt": "h:mm A",
23+
"hh:mm tt": "hh:mm A"
24+
};
25+
26+
// Helper function to format Graph date/time in the user's
27+
// preferred format
28+
function formatDateTime(dateTime: string | undefined, format: string) {
29+
if (dateTime !== undefined) {
30+
return moment(dateTime).format(formatMap[format] || format);
31+
}
32+
}
33+
34+
export default class CalendarDayRow extends React.Component<CalendarDayRowProps> {
35+
render() {
36+
var today = moment();
37+
var rowClass = today.day() === this.props.date?.day() ? 'table-warning' : '';
38+
var timeFormat = this.props.timeFormat;
39+
console.log(timeFormat);
40+
41+
var dateCell = (
42+
<td className='calendar-view-date-cell' rowSpan={this.props.events.length <= 0 ? 1 : this.props.events.length}>
43+
<div className='calendar-view-date float-left text-right'>{this.props.date?.format('DD')}</div>
44+
<div className='calendar-view-day'>{this.props.date?.format('dddd')}</div>
45+
<div className='calendar-view-month text-muted'>{this.props.date?.format('MMMM, YYYY')}</div>
46+
</td>
47+
);
48+
49+
if (this.props.events.length <= 0)
50+
{
51+
// Render an empty row for the day
52+
return (
53+
<tr className={rowClass}>
54+
{dateCell}
55+
<td></td>
56+
<td></td>
57+
</tr>
58+
);
59+
}
60+
61+
return (
62+
<React.Fragment>
63+
{this.props.events.map(
64+
function(event: Event, index: Number) {
65+
return (
66+
<tr className={rowClass} key={event.id}>
67+
{ index === 0 && dateCell }
68+
<td className="calendar-view-timespan">
69+
<div>{formatDateTime(event.start?.dateTime, timeFormat)} - {formatDateTime(event.end?.dateTime, timeFormat)}</div>
70+
</td>
71+
<td>
72+
<div className="calendar-view-subject">{event.subject}</div>
73+
<div className="calendar-view-organizer">{event.organizer?.emailAddress?.name}</div>
74+
</td>
75+
</tr>
76+
)
77+
}
78+
)}
79+
</React.Fragment>
80+
)
81+
}
82+
}
83+
// </CalendarDayRowSnippet>

demo/graph-tutorial/src/GraphService.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
import { Moment } from "moment";
5-
64
// <graphServiceSnippet1>
5+
import moment, { Moment } from 'moment';
6+
import { Event } from 'microsoft-graph';
7+
import { PageCollection, PageIterator } from '@microsoft/microsoft-graph-client';
8+
79
var graph = require('@microsoft/microsoft-graph-client');
810

911
function getAuthenticatedClient(accessToken: string) {
@@ -32,15 +34,15 @@ export async function getUserDetails(accessToken: string) {
3234
// </graphServiceSnippet1>
3335

3436
// <getUserWeekCalendarSnippet>
35-
export async function getUserWeekCalendar(accessToken: string, timeZone: string, startDate: Moment) {
37+
export async function getUserWeekCalendar(accessToken: string, timeZone: string, startDate: Moment): Promise<Event[]> {
3638
const client = getAuthenticatedClient(accessToken);
3739

3840
// Generate startDateTime and endDateTime query params
3941
// to display a 7-day window
4042
var startDateTime = startDate.format();
41-
var endDateTime = startDate.add(7, 'day').format();
43+
var endDateTime = moment(startDate).add(7, 'day').format();
4244

43-
const events = await client
45+
var response: PageCollection = await client
4446
.api('/me/calendarview')
4547
.header("Prefer", `outlook.timezone="${timeZone}"`)
4648
.query({ startDateTime: startDateTime, endDateTime: endDateTime })
@@ -49,6 +51,23 @@ export async function getUserWeekCalendar(accessToken: string, timeZone: string,
4951
.top(50)
5052
.get();
5153

52-
return events;
54+
if (response["@odata.nextLink"]) {
55+
// Presence of the nextLink property indicates more results are available
56+
// Use a page iterator to get all results
57+
var events: Event[] = [];
58+
59+
var pageIterator = new PageIterator(client, response, (event) => {
60+
events.push(event);
61+
return true;
62+
});
63+
64+
await pageIterator.iterate();
65+
66+
return events;
67+
} else {
68+
69+
return response.value;
70+
}
71+
5372
}
5473
// </getUserWeekCalendarSnippet>

0 commit comments

Comments
 (0)